<commit_before>/*
 * May GOD Bless this Code, amen! (Leave this line untouched)
 */
/**
 * @file         Hide/show DOM Elements
 * @author       [Kitanga Nday]{@link https://twitter.com/kitanga_nday}
 * @copyright    2016 Kitanga Nday All rights reserved
 * @license      [MIT License]{@link https://github.com/Kitanga/Impaka/blob/master/LICENSE}
 * @version      0.5.0
 */

/**
 * NDAYSwitchr - DOM element manipulator
 * @namespace NDAYSwitchr
 */
var NDAYSwitchr = ( /** @lends NDAYSwitchr */ function() {

    var self = this;
    /**
     * This is where all the groups are
     * @type {Object}
     */
    this.Groups = {};

    /**
     * This is the default name for the main group (when the user doesn't define a default name)
     * @type {String}
     */
    this.baseGroupName = 'Father';

    this.checkType = function(_obj, _type) {
        if (typeof _obj === 'string' && typeof _type === 'string') {
            var isType = undefined;
            switch (_type) {
                case 'string':
                    if (typeof _obj === 'string') {
                        isType = true;
                    } else {
                        isType = false;
                    };
                    break;
                case 'array':
                    if (_obj.constructor === Array) {
                        isType = true;
                    } else {
                        isType = false;
                    };
                    break;
                case 'undefined':
                    if (_obj === undefined) {
                        isType = true;
                    } else {
                        isType = false;
                    };
                    break;
                case 'function':
                    if (typeof _obj === 'function') {
                        isType = true;
                    } else {
                        isType = false;
                    };
                    break;
                case 'object':
                    if (typeof _obj === 'object') {
                        isType = true;
                    } else {
                        isType = false;
                    };
                    break;
                default:
                    console.error("Error: Something's up with parameter #2");
                    console.info('Just put the right type please.');
                    break;
            }

            if (isType !== undefined) {
                return isType;
            }
        } else {
            console.error("One/All of your params aren't strings");
            console.info('Please use valid datatype (aka strings!!!!!)');
        }
    };

    this.getFirst = function(_obj) {
        var toReturn = false;

        if (_obj) {
            for (var i in _obj) {
                toReturn = (_obj[i]) ? _obj[i] : false;
                break;
            }

            if (!toReturn) {
                console.error('There are no objects in the object.');
                console.info('Please add one or more objects inside the given object. So that this function can actually find the first element');
            }
        } else {
            console.error('There are no parameters');
            console.info('Please add an object in as a parameter');
        }

        return toReturn;
    };

    this.ifKeyExists = function(key, _obj) {
        var exists = false;
        for (var i in _obj) {
            if (i === key) {
                exists = true;
            }
        }

        return exists;
    };

    this.hideMe = function(_ele) {
        if (_ele) {
            _ele.hidden = (_ele.hidden) ? '' : true;
        } else {
            console.error('There are no parameters');
            console.info('Please add an html element in as a parameter');
        }
    };

    this.showMe = function(_ele) {
        if (_ele) {
            _ele.hidden = (_ele.hidden) ? false : '';
        } else {
            console.error('There are no parameters');
            console.info('Please add an html element in as a parameter');
        }
    };
    this.addGroup = function(group) {
        if (group) {
            if (self.checkType(group, 'string')) { /* If the parameter is a string... */
                this.createGroup(group); /* Create 1 group using the key as the key */
            } else if (self.checkType(group, 'array')) { /* If the param is an array... */
                for (var i = 0; i < group.length; i++) {
                    this.createGroup(group[i]); /* Create multiple group objects using the strings in array as keys*/
                }
            }
        } else {
            console.error('There are no parameters');
            console.info('Please add either a string or array of strings as parameter');
        }
    }
    this.createGroup = function(key) {
        this.Groups[key] = {};
        this.Groups[key].elements = {};
        this.Groups[key].getLength = function() {
            var counter = 0;
            for (var i in this) {
                counter++;
            }
            return counter;
        };

        /**
         * This is what is used to add DOM elements to the group
         * @param {string|array} key       This is the key(s) used to identify elements
         *
         * @param {string|array} id        The element's id(s) in the html code
         *
         * @param {string|array} hideHow   The class styles that will be used on the element to hide the element. This will affect all elements added using arrays. This stops the hide/show functions (and their variants) from being hidden using their hidden attribute. So make sure one of the classes has a 'display:none' style.
         *
         * @param {string|array} showHow   These are the styles that will be used when the element is being shown. Remember that having the hideHow param set means that showHow param is required
         */
        this.Groups[key].add = function(key, id /* Add this in v2.0.0 , hideHow, showHow */ ) {
            if (!self.ifKeyExists(key, this.elements)) {
                if (self.checkType(key, 'array') && self.checkType(id, 'array')) {
                    for (var i = 0; i < key.length; i++) {
                        this.elements[key[i]] = {
                            'domEle': document.getElementById(id[i])
                        };
                    }
                } else if (self.checkType(key, 'string') && self.checkType(id, 'string')) {
                    this.elements[key] = {
                        'domEle': document.getElementById(id)
                    };
                } else if (self.checkType(key, 'string') && self.checkType(id, 'undefined')) {
                    this.elements[key] = {
                        'domEle': document.getElementById(key)
                    };
                }
            } else {
                console.error("The key (" + key + ") already exists.");
                console.info("Please use a different key");
            }
        };
        this.Groups[key].hide = function(key, ftn) {
            if (self.checkType(key, 'string')) {
                /* If it's hidden, then keep it hidden. If not, then hide it. */
                self.hideMe(this.elements[key].domEle);
            } else if (!key) {
                var element = self.getFirst(this.elements);

                /* Is it more efficient to run code on the DOM */
                self.hideMe(element);
            }

            /* A custom function that runs after the element has been hidden */
            if (self.checkType(ftn, 'function') || self.checkType(key, 'function')) {
                var callBack = ftn || key;
                callback();
            }
        };

        this.Groups[key].hideAll = function(key) {

        };

        this.Groups[key].show = function(key,ftn) {
            if (self.checkType(key, 'string')) {
                /* Show element */
                self.showMe(this.elements[key].domEle);
            } else if (!key) {
                /* Show element */
                self.showMe(element);
            }

            /* A custom function that runs after the element has been hidden */
            if (self.checkType(ftn, 'function') || self.checkType(key, 'function')) {
                var callBack = ftn || key;
                callback();
            }
        };

        this.Groups[key].showAll = function() {
            //
        };
    };

    this.group = function(key) {

        /**
         * This is the object which will be returned for further work
         * @type {Object}
         */
        var toReturn = {};

        if (!key) {
            toReturn = this.getFirst(this.Groups);
            if (!toReturn) {
                console.error('There are no groups in the Group Object.');
                console.info('Please add one or more groups using the addGroup(key)');
            }
        } else if (key) {
            var keyFound = false; /* If the key has been found then reference the object it points to */
            for (var i in this.Groups) {
                if (key === i) {
                    toReturn = this.Groups[key];
                    keyFound = true;
                    break;
                }
            }
            if (!keyFound) {
                console.error('Your key: ' + key + '. was not found in the Group Object.');
                console.info('Please add this key using addGroup(key)');
                return false;
            }
        }
        console.log(this.Groups)
        return toReturn;
    };

    this.init = function(groupKey) {
        if (groupKey) {
            if (self.checkType(group, 'array')) {
                for (var i = 0; i < groupKey.length; i++) {
                    this.createGroup(groupKey[i]);
                }
            } else {
                console.error("Parameter 1's data type should be Array. Data type of inputted parameter " + typeof groupKey);
            }
            /* Comment the code block below because there's no need to rename the default group since it'll be the only one. User will most probably only call .group() since there's only one group */
            /* else if (typeof groupKey === 'string') {
                this.baseGroupName = key;
                this.groups[groupKey];
            }*/
        } else {
            this.createGroup(this.baseGroupName);
        }
    };

    return this;
})();
<commit_msg>Added all required functions for this API to become v1.0.0. But it's unstable though<commit_after>/*
 * May GOD Bless this Code, amen! (Leave this line untouched)
 */
/**
 * @file         Hide/show DOM Elements
 * @author       [Kitanga Nday]{@link https://twitter.com/kitanga_nday}
 * @copyright    2016 Kitanga Nday All rights reserved
 * @license      [MIT License]{@link https://github.com/Kitanga/Impaka/blob/master/LICENSE}
 * @version      0.5.0
 */

/**
 * NDAYSwitchr - DOM element manipulator
 * @namespace NDAYSwitchr
 */
var NDAYSwitchr = ( /** @lends NDAYSwitchr */ function() {

    var self = this;
    /**
     * This is where all the groups are
     * @type {Object}
     */
    this.Groups = {};

    /**
     * This is the default name for the main group (when the user doesn't define a default name)
     * @type {String}
     */
    this.baseGroupName = 'Father';

    this.checkType = function(_obj, _type) {
        if (typeof _obj === 'string' && typeof _type === 'string') {
            var isType = undefined;
            switch (_type) {
                case 'string':
                    if (typeof _obj === 'string') {
                        isType = true;
                    } else {
                        isType = false;
                    };
                    break;
                case 'array':
                    if (_obj.constructor === Array) {
                        isType = true;
                    } else {
                        isType = false;
                    };
                    break;
                case 'undefined':
                    if (_obj === undefined) {
                        isType = true;
                    } else {
                        isType = false;
                    };
                    break;
                case 'function':
                    if (typeof _obj === 'function') {
                        isType = true;
                    } else {
                        isType = false;
                    };
                    break;
                case 'object':
                    if (typeof _obj === 'object') {
                        isType = true;
                    } else {
                        isType = false;
                    };
                    break;
                default:
                    console.error("Error: Something's up with parameter #2");
                    console.info('Just put the right type please.');
                    break;
            }

            if (isType !== undefined) {
                return isType;
            }
        } else {
            console.error("One/All of your params aren't strings");
            console.info('Please use valid datatype (aka strings!!!!!)');
        }
    };

    this.getFirst = function(_obj) {
        var toReturn = false;

        if (_obj) {
            for (var i in _obj) {
                toReturn = (_obj[i]) ? _obj[i] : false;
                break;
            }

            if (!toReturn) {
                console.error('There are no objects in the object.');
                console.info('Please add one or more objects inside the given object. So that this function can actually find the first element');
            }
        } else {
            console.error('There are no parameters');
            console.info('Please add an object in as a parameter');
        }

        return toReturn;
    };

    this.ifKeyExists = function(key, _obj) {
        var exists = false;
        for (var i in _obj) {
            if (i === key) {
                exists = true;
            }
        }

        return exists;
    };

    this.hideMe = function(_ele) {
        if (_ele) {
            _ele.hidden = (_ele.hidden) ? '' : true;
        } else {
            console.error('There are no parameters');
            console.info('Please add an html element in as a parameter');
        }
    };

    this.showMe = function(_ele) {
        if (_ele) {
            _ele.hidden = (_ele.hidden) ? false : '';
        } else {
            console.error('There are no parameters');
            console.info('Please add an html element in as a parameter');
        }
    };
    this.addGroup = function(group) {
        if (group) {
            if (self.checkType(group, 'string')) { /* If the parameter is a string... */
                this.createGroup(group); /* Create 1 group using the key as the key */
            } else if (self.checkType(group, 'array')) { /* If the param is an array... */
                for (var i = 0; i < group.length; i++) {
                    this.createGroup(group[i]); /* Create multiple group objects using the strings in array as keys*/
                }
            }
        } else {
            console.error('There are no parameters');
            console.info('Please add either a string or array of strings as parameter');
        }
    }
    this.createGroup = function(key) {
        this.Groups[key] = {};
        this.Groups[key].elements = {};
        this.Groups[key].getLength = function() {
            var counter = 0;
            for (var i in this) {
                counter++;
            }
            return counter;
        };

        /**
         * This is what is used to add DOM elements to the group
         * @param {string|array} key       This is the key(s) used to identify elements
         *
         * @param {string|array} id        The element's id(s) in the html code
         *
         * @param {string|array} hideHow   The class styles that will be used on the element to hide the element. This will affect all elements added using arrays. This stops the hide/show functions (and their variants) from being hidden using their hidden attribute. So make sure one of the classes has a 'display:none' style.
         *
         * @param {string|array} showHow   These are the styles that will be used when the element is being shown. Remember that having the hideHow param set means that showHow param is required
         */
        this.Groups[key].add = function(key, id /* Add this in v2.0.0 , hideHow, showHow */ ) {
            if (!self.ifKeyExists(key, this.elements)) {
                if (self.checkType(key, 'array') && self.checkType(id, 'array')) {
                    for (var i = 0; i < key.length; i++) {
                        this.elements[key[i]] = {
                            'domEle': document.getElementById(id[i])
                        };
                    }
                } else if (self.checkType(key, 'string') && self.checkType(id, 'string')) {
                    this.elements[key] = {
                        'domEle': document.getElementById(id)
                    };
                } else if (self.checkType(key, 'string') && self.checkType(id, 'undefined')) {
                    this.elements[key] = {
                        'domEle': document.getElementById(key)
                    };
                }
            } else {
                console.error("The key (" + key + ") already exists.");
                console.info("Please use a different key");
            }
        };
        this.Groups[key].hide = function(key, ftn) {
            if (self.checkType(key, 'string')) {
                /* If it's hidden, then keep it hidden. If not, then hide it. */
                self.hideMe(this.elements[key].domEle);
            } else if (!key) {
                var element = self.getFirst(this.elements);

                self.hideMe(element.domEle);
            }

            /* A custom function that runs after the element has been hidden */
            if (self.checkType(ftn, 'function') || self.checkType(key, 'function')) {
                var callBack = ftn || key;
                callback();
            }
        };

        this.Groups[key].hideAll = function(key) {
            for (var i in this.elements) { /* For loop through elements and hide them */
                self.hideMe(this.elements[i].domEle); /* Hide the element */
            }
            if (!key) { /* If key doesn't exist */
                self.showMe(this.elements[key].domEle); /* This shows this element if the key param exists */
            }
        };

        this.Groups[key].show = function(key, ftn) {
            if (self.checkType(key, 'string')) {
                /* Show element */
                self.showMe(this.elements[key].domEle);
            } else if (!key) {
                var element = self.getFirst(this.elements); /* Get the first element in the elements object */
                /* Show element */
                self.showMe(element);
            }

            /* A custom function that runs after the element has been hidden */
            if (self.checkType(ftn, 'function') || self.checkType(key, 'function')) {
                var callBack = ftn || key;
                callback();
            }
        };

        this.Groups[key].showAll = function(key) {
            for (var i in this.elements) { /* For loop through elements and show them */
                self.showMe(this.elements[i].domEle); /* show this element */
            }
            if (!key) { /* If key doesn't exist */
                self.hideMe(this.elements[key].domEle); /* This hides this element if the key param exists */
            }
        };
    };

    this.group = function(key) {

        /**
         * This is the object which will be returned for further work
         * @type {Object}
         */
        var toReturn = {};

        if (!key) {
            toReturn = this.getFirst(this.Groups);
            if (!toReturn) {
                console.error('There are no groups in the Group Object.');
                console.info('Please add one or more groups using the addGroup(key)');
            }
        } else if (key) {
            var keyFound = false; /* If the key has been found then reference the object it points to */
            for (var i in this.Groups) {
                if (key === i) {
                    toReturn = this.Groups[key];
                    keyFound = true;
                    break;
                }
            }
            if (!keyFound) {
                console.error('Your key: ' + key + '. was not found in the Group Object.');
                console.info('Please add this key using addGroup(key)');
                return false;
            }
        }
        console.log(this.Groups)
        return toReturn;
    };

    this.init = function(groupKey) {
        if (groupKey) {
            if (self.checkType(group, 'array')) {
                for (var i = 0; i < groupKey.length; i++) {
                    this.createGroup(groupKey[i]);
                }
            } else {
                console.error("Parameter 1's data type should be Array. Data type of inputted parameter " + typeof groupKey);
            }
            /* Comment the code block below because there's no need to rename the default group since it'll be the only one. User will most probably only call .group() since there's only one group */
            /* else if (typeof groupKey === 'string') {
                this.baseGroupName = key;
                this.groups[groupKey];
            }*/
        } else {
            this.createGroup(this.baseGroupName);
        }
    };

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


<commit_before>var cookie = require('cookie');
var FastBootHeaders = require('./fastboot-headers');

function FastBootRequest(request, hostWhitelist) {
  this.hostWhitelist = hostWhitelist;

  this.protocol = request.protocol;
  this.headers = new FastBootHeaders(request.headers);
  this.queryParams = request.query;
  this.path = request.url;
  this.method = request.method;
  this.body = request.body;

  this.cookies = this.extractCookies(request);
}

FastBootRequest.prototype.host = function() {
  if (!this.hostWhitelist) {
    throw new Error('You must provide a hostWhitelist to retrieve the host');
  }

  var host = this.headers.get('host');

  var matchFound = this.hostWhitelist.reduce(function(previous, currentEntry) {
    if (currentEntry[0] === '/' &&
        currentEntry.slice(-1) === '/') {
      // RegExp as string
      var regexp = new RegExp(currentEntry.slice(1, -1));

      return previous || regexp.test(host);
    } else {
      return previous || currentEntry === host;
    }
  }, false);

  if (!matchFound) {
    throw new Error(`The host header did not match a hostWhitelist entry. Host header: ${host}`);
  }

  return host;
};

FastBootRequest.prototype.extractCookies = function(request) {
  // If cookie-parser middleware has already parsed the cookies,
  // just use that.
  if (request.cookies) {
    return request.cookies;
  }

  // Otherwise, try to parse the cookies ourselves, if they exist.
  var cookies = request.headers.cookie;
  if (cookies) {
    return cookie.parse(cookies);
  }

  // Return an empty object instead of undefined if no cookies are present.
  return {};
};

module.exports = FastBootRequest;
<commit_msg>convert FastBootRequest to es6 class<commit_after>'use strict';

var cookie = require('cookie');
var FastBootHeaders = require('./fastboot-headers');

class FastBootRequest {
  constructor(request, hostWhitelist) {
    this.hostWhitelist = hostWhitelist;

    this.protocol = request.protocol;
    this.headers = new FastBootHeaders(request.headers);
    this.queryParams = request.query;
    this.path = request.url;
    this.method = request.method;
    this.body = request.body;

    this.cookies = this.extractCookies(request);
  }

  host() {
    if (!this.hostWhitelist) {
      throw new Error('You must provide a hostWhitelist to retrieve the host');
    }

    var host = this.headers.get('host');

    var matchFound = this.hostWhitelist.reduce(function(previous, currentEntry) {
      if (currentEntry[0] === '/' &&
          currentEntry.slice(-1) === '/') {
        // RegExp as string
        var regexp = new RegExp(currentEntry.slice(1, -1));

        return previous || regexp.test(host);
      } else {
        return previous || currentEntry === host;
      }
    }, false);

    if (!matchFound) {
      throw new Error(`The host header did not match a hostWhitelist entry. Host header: ${host}`);
    }

    return host;
  }

  extractCookies(request) {
    // If cookie-parser middleware has already parsed the cookies,
    // just use that.
    if (request.cookies) {
      return request.cookies;
    }

    // Otherwise, try to parse the cookies ourselves, if they exist.
    var cookies = request.headers.cookie;
    if (cookies) {
      return cookie.parse(cookies);
    }

    // Return an empty object instead of undefined if no cookies are present.
    return {};
  }

}

module.exports = FastBootRequest;
<|endoftext|>


<commit_before>/*!
Filterize, a jQuery Plugin to filter select list
by Eduard Deza at Hiringo Team, http://hiringo.com

Version 1.0.0
Full source at https://github.com/edezacas/Filterize
*/

;(function ($, window, document, undefined) {

    var pluginName = 'filterize';

    function Plugin (element, options) {
        this.element = element;
        this._name = pluginName;
        this._defaults = $.fn[pluginName].defaults;
        this.options = $.extend( {}, this._defaults, options );

        this.init();
    }

    $.extend(Plugin.prototype, {

        // Initialization logic
        init: function () {
	        this.buildWrapper();
            this.buildSelect();
            this.buildCache();
            this.bindEvents();
        },
		//Build Wrapper for Select List
		buildWrapper: function(){
			var select = $(this.element);

			select
			.wrap('

')
			.append('<option class="filterize-no_results" value="no-results">'+this.options.noresultsText+'</option>');

			var parent = select.parent();
			parent.prepend('
'+this.options.titleText+'

');
		},
		//Build Select Custom List
		buildSelect: function(){
			var select = $(this.element),
				parent = select.parent(),
				boxList = parent.find('.filterize-list'),
				list = parent.find('ul'),
				title = parent.find('.filterize-title');

			title.css('min-width',title.outerWidth());

			for(var i = 0,len = select.children('option').length;i < len;i++){
				var option = select.children('option').eq(i),
					clase = option.attr("class");

				if(typeof clase == "undefined"){
					clase = "";
				}

				list.append('

'+option.text()+'

')
			}

			boxList.prepend('
<input type="text" autocomplete="off" tabindex="1">
');

			select.hide();

			// open list
			title.on('click', function(){
				boxList.stop(true, true).slideToggle();
				$(this).toggleClass('active');
			});

			this.fireSearch();
		},
        // Cache DOM nodes for performance
        buildCache: function () {
            this.$element = $(this.element);
        },

        // Bind events that trigger methods
        bindEvents: function() {
            var plugin = this;

            plugin.$element.on('filterize:update'+'.'+plugin._name, function() {
                plugin.update.call(plugin);
            });
        },
        //Search input value on list
        fireSearch: function(){

			var select = $(this.element),
				parent = select.parent(),
				boxList = parent.find('.filterize-list'),
				list = parent.find('ul'),
				title = parent.find('.filterize-title');

			// selected option

			list.on('click','li',function(){

				var val = $(this).data("value"),
					texto = $(this).find("p").text();

				title.text(texto);
				boxList.slideUp();

				select.val(val);

				//Trigger change event to notify
				select.trigger("change");

				title.toggleClass('active');

			});

			$('.filterize-list-search input').on('change', function(){
			    var filter = $(this).val(),
			    	list = 	parent.find('ul')
			    	elNoRes = $(list).find(".filterize-no_results");

			    if(filter) {
			      // this finds all links in a list that contain the input,
			      // and hide the ones not containing the input while showing the ones that do
			      $(list).find("p:not(:Contains(" + filter + "))").parent().stop(true, false).hide();
			      $(list).find("p:Contains(" + filter + ")").parent().stop(true, false).show();
			      elNoRes.stop(true, false).hide();

			      //No results
			      if(!$(list).find("p:Contains(" + filter + ")").length){
				      elNoRes.stop(true, false).show();
			      }

			    } else {
					elNoRes.stop(true, false).hide();
					$(list).find("li:not(.filterize-no_results)").show();
			    }

			    return false;
			  })
			.keyup( function () {
			    // fire the above change event after every letter
			    $(this).change();
			});

			// custom css expression for a case-insensitive contains()
			jQuery.expr[':'].Contains = function(a,i,m){
			    return (a.textContent || a.innerText || "").toUpperCase().indexOf(m[3].toUpperCase())>=0;
			};

        }

    });

    $.fn[pluginName] = function (options) {
        this.each(function() {
            if ( !$.data( this, "plugin_" + pluginName ) ) {
                $.data( this, "plugin_" + pluginName, new Plugin( this, options ) );
            }
        });
        return this;
    };

    $.fn[pluginName].defaults = {
        titleText: 'Select an option',
	    noresultsText: 'No results matched'
    };

})( jQuery, window, document );
<commit_msg>Cache the list to improve performance<commit_after>/*!
Filterize, a jQuery Plugin to filter select list
by Eduard Deza at Hiringo Team, http://hiringo.com

Version 1.0.0
Full source at https://github.com/edezacas/Filterize
*/

;(function ($, window, document, undefined) {

    var pluginName = 'filterize';

    function Plugin (element, options) {
        this.element = element;
        this._name = pluginName;
        this._defaults = $.fn[pluginName].defaults;
        this.options = $.extend( {}, this._defaults, options );

        this.init();
    }

    $.extend(Plugin.prototype, {

        // Initialization logic
        init: function () {
	        this.buildWrapper();
            this.buildSelect();
            this.buildCache();
            this.bindEvents();
        },
		//Build Wrapper for Select List
		buildWrapper: function(){
			var select = $(this.element);

			select
			.wrap('

')
			.append('<option class="filterize-no_results" value="no-results">'+this.options.noresultsText+'</option>');

			var parent = select.parent();
			parent.prepend('
'+this.options.titleText+'

');
		},
		//Build Select Custom List
		buildSelect: function(){
			var select = $(this.element),
				parent = select.parent(),
				boxList = parent.find('.filterize-list'),
				list = parent.find('ul'),
				title = parent.find('.filterize-title');

			title.css('min-width',title.outerWidth());

			for(var i = 0,len = select.children('option').length;i < len;i++){
				var option = select.children('option').eq(i),
					clase = option.attr("class");

				if(typeof clase == "undefined"){
					clase = "";
				}

				list.append('

'+option.text()+'

')
			}

			boxList.prepend('
<input type="text" autocomplete="off" tabindex="1">
');

			select.hide();

			// open list
			title.on('click', function(){
				boxList.stop(true, true).slideToggle();
				$(this).toggleClass('active');
			});

			this.fireSearch();
		},
        // Cache DOM nodes for performance
        buildCache: function () {
            this.$element = $(this.element);
        },

        // Bind events that trigger methods
        bindEvents: function() {
            var plugin = this;

            plugin.$element.on('filterize:update'+'.'+plugin._name, function() {
                plugin.update.call(plugin);
            });
        },
        //Search input value on list
        fireSearch: function(){

			var select = $(this.element),
				parent = select.parent(),
				boxList = parent.find('.filterize-list'),
				list = parent.find('ul'),
				title = parent.find('.filterize-title');

			// selected option

			list.on('click','li',function(){

				var val = $(this).data("value"),
					texto = $(this).find("p").text();

				title.text(texto);
				boxList.slideUp();

				select.val(val);

				//Trigger change event to notify
				select.trigger("change");

				title.toggleClass('active');

			});

			$('.filterize-list-search input').on('change', function(){
			    var filter = $(this).val(),
			    	list = 	parent.find('ul')
			    	elNoRes = $(list).find(".filterize-no_results");

			    if(filter) {
			      // this finds all links in a list that contain the input,
			      // and hide the ones not containing the input while showing the ones that do
				  var matches = $(list).find('p:Contains(' + filter + ')'),
				  	  matchesParent = matches.parent();

				  $('li', list).not(matchesParent).stop(true, false).hide();
				  matchesParent.stop(true, false).show();
			      elNoRes.stop(true, false).hide();

			      //No results
			      if(!matches.length){
				      elNoRes.stop(true, false).show();
			      }

			    } else {
					elNoRes.stop(true, false).hide();
					$(list).find("li:not(.filterize-no_results)").show();
			    }

			    return false;
			  })
			.keyup( function () {
			    // fire the above change event after every letter
			    $(this).change();
			});

			// custom css expression for a case-insensitive contains()
			jQuery.expr[':'].Contains = function(a,i,m){
			    return (a.textContent || a.innerText || "").toUpperCase().indexOf(m[3].toUpperCase())>=0;
			};

        }

    });

    $.fn[pluginName] = function (options) {
        this.each(function() {
            if ( !$.data( this, "plugin_" + pluginName ) ) {
                $.data( this, "plugin_" + pluginName, new Plugin( this, options ) );
            }
        });
        return this;
    };

    $.fn[pluginName].defaults = {
        titleText: 'Select an option',
	    noresultsText: 'No results matched'
    };

})( jQuery, window, document );
<|endoftext|>


<commit_before>import list from "./list";

export default function(circles) {
  return encloseN(list(circles), []);
}

function encloses(a, b) {
  var dr = a.r - b.r, dx = b.x - a.x, dy = b.y - a.y;
  return dr >= -1e-6 && dr * dr * 1.000001 > dx * dx + dy * dy;
}

// Returns the smallest circle that contains circles L and intersects circles B.
function encloseN(L, B) {
  var circle,
      l0 = null,
      l1 = L.head,
      l2,
      p1;

  switch (B.length) {
    case 0: break;
    case 1: circle = enclose1(B[0]); break;
    case 2: circle = enclose2(B[0], B[1]); break;
    case 3: circle = enclose3(B[0], B[1], B[2]); break;
    default: return null;
  }

  while (l1) {
    p1 = l1._, l2 = l1.next;
    if (!circle || !encloses(circle, p1)) {

      // Temporarily truncate L before l1.
      if (l0) L.tail = l0, l0.next = null;
      else L.head = L.tail = null;

      B.push(p1);
      circle = encloseN(L, B); // Note: reorders L!
      B.pop();

      // Move l1 to the front of L and reconnect the truncated list L.
      if (L.head) l1.next = L.head, L.head = l1;
      else l1.next = null, L.head = L.tail = l1;
      l0 = L.tail, l0.next = l2;

    } else {
      l0 = l1;
    }
    l1 = l2;
  }

  L.tail = l0;
  return circle;
}

function enclose1(a) {
  return {
    x: a.x,
    y: a.y,
    r: a.r
  };
}

function enclose2(a, b) {
  var x1 = a.x, y1 = a.y, r1 = a.r,
      x2 = b.x, y2 = b.y, r2 = b.r,
      x21 = x2 - x1, y21 = y2 - y1, r21 = r2 - r1,
      l = Math.sqrt(x21 * x21 + y21 * y21);
  return {
    x: (x1 + x2 + x21 / l * r21) / 2,
    y: (y1 + y2 + y21 / l * r21) / 2,
    r: (l + r1 + r2) / 2
  };
}

function enclose3(a, b, c) {
  var x1 = a.x, y1 = a.y, r1 = a.r,
      x2 = b.x, y2 = b.y, r2 = b.r,
      x3 = c.x, y3 = c.y, r3 = c.r,
      a2 = x1 - x2,
      a3 = x1 - x3,
      b2 = y1 - y2,
      b3 = y1 - y3,
      c2 = r2 - r1,
      c3 = r3 - r1,
      d1 = x1 * x1 + y1 * y1 - r1 * r1,
      d2 = d1 - x2 * x2 - y2 * y2 + r2 * r2,
      d3 = d1 - x3 * x3 - y3 * y3 + r3 * r3,
      ab = a3 * b2 - a2 * b3,
      xa = (b2 * d3 - b3 * d2) / (ab * 2) - x1,
      xb = (b3 * c2 - b2 * c3) / ab,
      ya = (a3 * d2 - a2 * d3) / (ab * 2) - y1,
      yb = (a2 * c3 - a3 * c2) / ab,
      A = xb * xb + yb * yb - 1,
      B = 2 * (r1 + xa * xb + ya * yb),
      C = xa * xa + ya * ya - r1 * r1,
      r = -(A ? (B + Math.sqrt(B * B - 4 * A * C)) / (2 * A) : C / B);
  return {
    x: x1 + xa + xb * r,
    y: y1 + ya + yb * r,
    r: r
  };
}
<commit_msg>More-accurate enclose3.<commit_after>import list from "./list";

export default function(circles) {
  return encloseN(list(circles), []);
}

function encloses(a, b) {
  var dr = a.r - b.r, dx = b.x - a.x, dy = b.y - a.y;
  return dr >= -1e-6 && dr * dr * 1.000001 > dx * dx + dy * dy;
}

// Returns the smallest circle that contains circles L and intersects circles B.
function encloseN(L, B) {
  var circle,
      l0 = null,
      l1 = L.head,
      l2,
      p1;

  switch (B.length) {
    case 0: break;
    case 1: circle = enclose1(B[0]); break;
    case 2: circle = enclose2(B[0], B[1]); break;
    case 3: circle = enclose3(B[0], B[1], B[2]); break;
    default: return null;
  }

  while (l1) {
    p1 = l1._, l2 = l1.next;
    if (!circle || !encloses(circle, p1)) {

      // Temporarily truncate L before l1.
      if (l0) L.tail = l0, l0.next = null;
      else L.head = L.tail = null;

      B.push(p1);
      circle = encloseN(L, B); // Note: reorders L!
      B.pop();

      // Move l1 to the front of L and reconnect the truncated list L.
      if (L.head) l1.next = L.head, L.head = l1;
      else l1.next = null, L.head = L.tail = l1;
      l0 = L.tail, l0.next = l2;

    } else {
      l0 = l1;
    }
    l1 = l2;
  }

  L.tail = l0;
  return circle;
}

function enclose1(a) {
  return {
    x: a.x,
    y: a.y,
    r: a.r
  };
}

function enclose2(a, b) {
  var x1 = a.x, y1 = a.y, r1 = a.r,
      x2 = b.x, y2 = b.y, r2 = b.r,
      x21 = x2 - x1, y21 = y2 - y1, r21 = r2 - r1,
      l = Math.sqrt(x21 * x21 + y21 * y21);
  return {
    x: (x1 + x2 + x21 / l * r21) / 2,
    y: (y1 + y2 + y21 / l * r21) / 2,
    r: (l + r1 + r2) / 2
  };
}

function enclose3(a, b, c) {
  var x1 = a.x, y1 = a.y, r1 = a.r,
      x2 = b.x, y2 = b.y, r2 = b.r,
      x3 = c.x, y3 = c.y, r3 = c.r,
      a2 = x1 - x2,
      a3 = x1 - x3,
      b2 = y1 - y2,
      b3 = y1 - y3,
      c2 = r2 - r1,
      c3 = r3 - r1,
      d1 = x1 * x1 + y1 * y1 - r1 * r1,
      d2 = d1 - x2 * x2 - y2 * y2 + r2 * r2,
      d3 = d1 - x3 * x3 - y3 * y3 + r3 * r3,
      ab = a3 * b2 - a2 * b3,
      xa = (b2 * d3 - b3 * d2) / (ab * 2) - x1,
      xb = (b3 * c2 - b2 * c3) / ab,
      ya = (a3 * d2 - a2 * d3) / (ab * 2) - y1,
      yb = (a2 * c3 - a3 * c2) / ab,
      A = xb * xb + yb * yb - 1,
      B = 2 * (r1 + xa * xb + ya * yb),
      C = xa * xa + ya * ya - r1 * r1,
      r = A ? (B + Math.sqrt(B * B - 4 * A * C)) / (2 * A) : C / B,
      x = x1 + xa - xb * r,
      y = y1 + ya - yb * r;
  return {
    x: x,
    y: y,
    r: Math.max(
      Math.sqrt((x1 -= x) * x1 + (y1 -= y) * y1) + r1,
      Math.sqrt((x2 -= x) * x2 + (y2 -= y) * y2) + r2,
      Math.sqrt((x3 -= x) * x3 + (y3 -= y) * y3) + r3
    )
  };
}
<|endoftext|>


<commit_before>import { formatNumber, formatPercentage } from 'common/format';

import Status from './Modules/Status';
import HealingDone from './Modules/HealingDone';
import DamageDone from './Modules/DamageDone';
import DamageTaken from './Modules/DamageTaken';

import Combatants from './Modules/Combatants';
import AbilityTracker from './Modules/AbilityTracker';
import AlwaysBeCasting from './Modules/AlwaysBeCasting';
import Enemies from './Modules/Enemies';
import HealEventTracker from './Modules/HealEventTracker';
import ManaValues from './Modules/ManaValues';
import SpellManaCost from './Modules/SpellManaCost';
import CritEffectBonus from './Modules/Helpers/CritEffectBonus';

// Shared Legendaries
import Prydaz from './Modules/Items/Prydaz';
import Velens from './Modules/Items/Velens';
import SephuzsSecret from './Modules/Items/SephuzsSecret';
import KiljaedensBurningWish from './Modules/Items/KiljaedensBurningWish';
import ArchimondesHatredReborn from './Modules/Items/ArchimondesHatredReborn';
// Shared Epics
import DrapeOfShame from './Modules/Items/DrapeOfShame';
import DarkmoonDeckPromises from './Modules/Items/DarkmoonDeckPromises';
import AmalgamsSeventhSpine from './Modules/Items/AmalgamsSeventhSpine';
import ArchiveOfFaith from './Modules/Items/ArchiveOfFaith';
import BarbaricMindslaver from './Modules/Items/BarbaricMindslaver';
import SeaStar from './Modules/Items/SeaStarOfTheDepthmother';
import DeceiversGrandDesign from './Modules/Items/DeceiversGrandDesign';
import PrePotion from './Modules/Items/PrePotion';
import GnawedThumbRing from './Modules/Items/GnawedThumbRing';
import VialOfCeaselessToxins from './Modules/Items/VialOfCeaselessToxins';
import SpecterOfBetrayal from './Modules/Items/SpecterOfBetrayal';
import EngineOfEradication from './Modules/Items/EngineOfEradication';
import TarnishedSentinelMedallion from './Modules/Items/TarnishedSentinelMedallion';
import SpectralThurible from './Modules/Items/SpectralThurible';
import TerrorFromBelow from './Modules/Items/TerrorFromBelow';
import TomeOfUnravelingSanity from './Modules/Items/TomeOfUnravelingSanity';

// Shared Buffs
import VantusRune from './Modules/VantusRune';

import ParseResults from './ParseResults';

const debug = false;

class CombatLogParser {
  static abilitiesAffectedByHealingIncreases = [];

  static defaultModules = {
    status: Status,
    healingDone: HealingDone,
    damageDone: DamageDone,
    damageTaken: DamageTaken,

    combatants: Combatants,
    enemies: Enemies,
    spellManaCost: SpellManaCost,
    abilityTracker: AbilityTracker,
    healEventTracker: HealEventTracker,
    alwaysBeCasting: AlwaysBeCasting,
    manaValues: ManaValues,
    vantusRune: VantusRune,

    critEffectBonus: CritEffectBonus,

    // Items:
    // Legendaries:
    prydaz: Prydaz,
    velens: Velens,
    sephuzsSecret: SephuzsSecret,
    kiljaedensBurningWish: KiljaedensBurningWish,
    archimondesHatredReborn: ArchimondesHatredReborn,
    // Epics:
    drapeOfShame: DrapeOfShame,
    amalgamsSeventhSpine: AmalgamsSeventhSpine,
    darkmoonDeckPromises: DarkmoonDeckPromises,
    prePotion: PrePotion,
    gnawedThumbRing: GnawedThumbRing,
    // Tomb trinkets:
    archiveOfFaith: ArchiveOfFaith,
    barbaricMindslaver: BarbaricMindslaver,
    seaStar: SeaStar,
    deceiversGrandDesign: DeceiversGrandDesign,
    vialCeaslessToxins: VialOfCeaselessToxins,
    specterOfBetrayal: SpecterOfBetrayal,
    engineOfEradication: EngineOfEradication,
    tarnishedSentinelMedallion: TarnishedSentinelMedallion,
    spectralThurible: SpectralThurible,
    terrorFromBelow: TerrorFromBelow,
    tomeOfUnravelingSanity: TomeOfUnravelingSanity,
  };
  // Override this with spec specific modules
  static specModules = {};

  report = null;
  player = null;
  fight = null;

  modules = {};
  get activeModules() {
    return Object.keys(this.modules)
      .map(key => this.modules[key])
      .filter(module => module.active);
  }

  get playerId() {
    return this.player.id;
  }

  /** @returns Combatants */
  get combatants() {
    return this.modules.combatants;
  }
  get playerCount() {
    return this.modules.combatants.playerCount;
  }

  /** @returns {Combatant} */
  get selectedCombatant() {
    return this.combatants.selected;
  }

  get currentTimestamp() {
    return this.finished ? this.fight.end_time : this._timestamp;
  }
  get fightDuration() {
    return this.currentTimestamp - this.fight.start_time;
  }
  get finished() {
    return this.modules.status.finished;
  }

  get playersById() {
    return this.report.friendlies.reduce((obj, player) => {
      obj[player.id] = player;
      return obj;
    }, {});
  }

  constructor(report, player, fight) {
    this.report = report;
    this.player = player;
    this.fight = fight;

    this.initializeModules({
      ...this.constructor.defaultModules,
      ...this.constructor.specModules,
    });
  }

  initializeModules(modules) {
    const failedModules = [];
    Object.keys(modules).forEach(desiredModuleName => {
      const moduleClass = modules[desiredModuleName];
      if (!moduleClass) {
        return;
      }

      const availableDependencies = {};
      const missingDependencies = [];
      if (moduleClass.dependencies) {
        Object.keys(moduleClass.dependencies).forEach(desiredDependencyName => {
          const dependencyClass = moduleClass.dependencies[desiredDependencyName];

          const dependencyModule = this.findModule(dependencyClass);
          if (dependencyModule) {
            availableDependencies[desiredDependencyName] = dependencyModule;
          } else {
            missingDependencies.push(dependencyClass);
          }
        });
      }

      if (missingDependencies.length === 0) {
        if (debug) {
          if (Object.keys(availableDependencies).length === 0) {
            console.log('Loading', moduleClass.name);
          } else {
            console.log('Loading', moduleClass.name, 'with dependencies:', Object.keys(availableDependencies));
          }
        }
        this.modules[desiredModuleName] = new moduleClass(this, availableDependencies, Object.keys(this.modules).length);
      } else {
        debug && console.warn(moduleClass.name, 'could not be loaded, missing dependencies:', missingDependencies.map(d => d.name));
        failedModules.push(desiredModuleName);
      }
    });

    if (failedModules.length !== 0) {
      debug && console.warn(`${failedModules.length} modules failed to load, trying again:`, failedModules.map(key => modules[key].name));
      const newBatch = {};
      failedModules.forEach(key => {
        newBatch[key] = modules[key];
      });
      this.initializeModules(newBatch);
    }
  }
  findModule(type) {
    return Object.keys(this.modules)
      .map(key => this.modules[key])
      .find(module => module instanceof type);
  }

  _debugEventHistory = [];
  parseEvents(events) {
    if (process.env.NODE_ENV === 'development') {
      this._debugEventHistory = [
        ...this._debugEventHistory,
        ...events,
      ];
    }
    return new Promise((resolve, reject) => {
      events.forEach(event => {
        if (this.error) {
          throw new Error(this.error);
        }
        this._timestamp = event.timestamp;

        // Triggering a lot of events here for development pleasure; does this have a significant performance impact?
        this.triggerEvent(event.type, event);
      });

      resolve(events.length);
    });
  }
  triggerEvent(eventType, event, ...args) {
    this.activeModules
      .sort((a, b) => a.priority - b.priority) // lowest should go first, as `priority = 0` will have highest prio
      .forEach(module => {
        module.triggerEvent('event', eventType, event, ...args);
        module.triggerEvent(eventType, event, ...args);
        if (event && this.byPlayer(event)) {
          module.triggerEvent(`byPlayer_${eventType}`, event, ...args);
        }
        if (event && this.toPlayer(event)) {
          module.triggerEvent(`toPlayer_${eventType}`, event, ...args);
        }
      });
  }

  byPlayer(event, playerId = this.player.id) {
    return (event.sourceID === playerId);
  }
  toPlayer(event, playerId = this.player.id) {
    return (event.targetID === playerId);
  }

  // TODO: Damage taken from LOTM

  getPercentageOfTotalHealingDone(healingDone) {
    return healingDone / this.modules.healingDone.total.effective;
  }
  formatItemHealingDone(healingDone) {
    return `${formatPercentage(this.getPercentageOfTotalHealingDone(healingDone))} % / ${formatNumber(healingDone / this.fightDuration * 1000)} HPS`;
  }
  formatItemAbsorbDone(absorbDone) {
    return `${formatNumber(absorbDone)}`;
  }
  getPercentageOfTotalDamageDone(damageDone) {
    return damageDone / this.modules.damageDone.total.effective;
  }
  formatItemDamageDone(damageDone) {
    return `${formatPercentage(this.getPercentageOfTotalDamageDone(damageDone))} % / ${formatNumber(damageDone / this.fightDuration * 1000)} DPS`;
  }

  generateResults() {
    const results = new ParseResults();

    this.activeModules
      .sort((a, b) => b.priority - a.priority)
      .forEach(module => {
        if (module.statistic) {
          const statistic = module.statistic();
          if (statistic) {
            results.statistics.push({
              statistic,
              order: module.statisticOrder,
            });
          }
        }
        if (module.item) {
          const item = module.item();
          if (item) {
            results.items.push(item);
          }
        }
        if (module.tab) {
          const tab = module.tab();
          if (tab) {
            results.tabs.push(tab);
          }
        }
        if (module.suggestions) {
          module.suggestions(results.suggestions.when);
        }
      });

    return results;
  }
}

export default CombatLogParser;
<commit_msg>Fix to on_event<commit_after>import { formatNumber, formatPercentage } from 'common/format';

import Status from './Modules/Status';
import HealingDone from './Modules/HealingDone';
import DamageDone from './Modules/DamageDone';
import DamageTaken from './Modules/DamageTaken';

import Combatants from './Modules/Combatants';
import AbilityTracker from './Modules/AbilityTracker';
import AlwaysBeCasting from './Modules/AlwaysBeCasting';
import Enemies from './Modules/Enemies';
import HealEventTracker from './Modules/HealEventTracker';
import ManaValues from './Modules/ManaValues';
import SpellManaCost from './Modules/SpellManaCost';
import CritEffectBonus from './Modules/Helpers/CritEffectBonus';

// Shared Legendaries
import Prydaz from './Modules/Items/Prydaz';
import Velens from './Modules/Items/Velens';
import SephuzsSecret from './Modules/Items/SephuzsSecret';
import KiljaedensBurningWish from './Modules/Items/KiljaedensBurningWish';
import ArchimondesHatredReborn from './Modules/Items/ArchimondesHatredReborn';
// Shared Epics
import DrapeOfShame from './Modules/Items/DrapeOfShame';
import DarkmoonDeckPromises from './Modules/Items/DarkmoonDeckPromises';
import AmalgamsSeventhSpine from './Modules/Items/AmalgamsSeventhSpine';
import ArchiveOfFaith from './Modules/Items/ArchiveOfFaith';
import BarbaricMindslaver from './Modules/Items/BarbaricMindslaver';
import SeaStar from './Modules/Items/SeaStarOfTheDepthmother';
import DeceiversGrandDesign from './Modules/Items/DeceiversGrandDesign';
import PrePotion from './Modules/Items/PrePotion';
import GnawedThumbRing from './Modules/Items/GnawedThumbRing';
import VialOfCeaselessToxins from './Modules/Items/VialOfCeaselessToxins';
import SpecterOfBetrayal from './Modules/Items/SpecterOfBetrayal';
import EngineOfEradication from './Modules/Items/EngineOfEradication';
import TarnishedSentinelMedallion from './Modules/Items/TarnishedSentinelMedallion';
import SpectralThurible from './Modules/Items/SpectralThurible';
import TerrorFromBelow from './Modules/Items/TerrorFromBelow';
import TomeOfUnravelingSanity from './Modules/Items/TomeOfUnravelingSanity';

// Shared Buffs
import VantusRune from './Modules/VantusRune';

import ParseResults from './ParseResults';

const debug = false;

class CombatLogParser {
  static abilitiesAffectedByHealingIncreases = [];

  static defaultModules = {
    status: Status,
    healingDone: HealingDone,
    damageDone: DamageDone,
    damageTaken: DamageTaken,

    combatants: Combatants,
    enemies: Enemies,
    spellManaCost: SpellManaCost,
    abilityTracker: AbilityTracker,
    healEventTracker: HealEventTracker,
    alwaysBeCasting: AlwaysBeCasting,
    manaValues: ManaValues,
    vantusRune: VantusRune,

    critEffectBonus: CritEffectBonus,

    // Items:
    // Legendaries:
    prydaz: Prydaz,
    velens: Velens,
    sephuzsSecret: SephuzsSecret,
    kiljaedensBurningWish: KiljaedensBurningWish,
    archimondesHatredReborn: ArchimondesHatredReborn,
    // Epics:
    drapeOfShame: DrapeOfShame,
    amalgamsSeventhSpine: AmalgamsSeventhSpine,
    darkmoonDeckPromises: DarkmoonDeckPromises,
    prePotion: PrePotion,
    gnawedThumbRing: GnawedThumbRing,
    // Tomb trinkets:
    archiveOfFaith: ArchiveOfFaith,
    barbaricMindslaver: BarbaricMindslaver,
    seaStar: SeaStar,
    deceiversGrandDesign: DeceiversGrandDesign,
    vialCeaslessToxins: VialOfCeaselessToxins,
    specterOfBetrayal: SpecterOfBetrayal,
    engineOfEradication: EngineOfEradication,
    tarnishedSentinelMedallion: TarnishedSentinelMedallion,
    spectralThurible: SpectralThurible,
    terrorFromBelow: TerrorFromBelow,
    tomeOfUnravelingSanity: TomeOfUnravelingSanity,
  };
  // Override this with spec specific modules
  static specModules = {};

  report = null;
  player = null;
  fight = null;

  modules = {};
  get activeModules() {
    return Object.keys(this.modules)
      .map(key => this.modules[key])
      .filter(module => module.active);
  }

  get playerId() {
    return this.player.id;
  }

  /** @returns Combatants */
  get combatants() {
    return this.modules.combatants;
  }
  get playerCount() {
    return this.modules.combatants.playerCount;
  }

  /** @returns {Combatant} */
  get selectedCombatant() {
    return this.combatants.selected;
  }

  get currentTimestamp() {
    return this.finished ? this.fight.end_time : this._timestamp;
  }
  get fightDuration() {
    return this.currentTimestamp - this.fight.start_time;
  }
  get finished() {
    return this.modules.status.finished;
  }

  get playersById() {
    return this.report.friendlies.reduce((obj, player) => {
      obj[player.id] = player;
      return obj;
    }, {});
  }

  constructor(report, player, fight) {
    this.report = report;
    this.player = player;
    this.fight = fight;

    this.initializeModules({
      ...this.constructor.defaultModules,
      ...this.constructor.specModules,
    });
  }

  initializeModules(modules) {
    const failedModules = [];
    Object.keys(modules).forEach(desiredModuleName => {
      const moduleClass = modules[desiredModuleName];
      if (!moduleClass) {
        return;
      }

      const availableDependencies = {};
      const missingDependencies = [];
      if (moduleClass.dependencies) {
        Object.keys(moduleClass.dependencies).forEach(desiredDependencyName => {
          const dependencyClass = moduleClass.dependencies[desiredDependencyName];

          const dependencyModule = this.findModule(dependencyClass);
          if (dependencyModule) {
            availableDependencies[desiredDependencyName] = dependencyModule;
          } else {
            missingDependencies.push(dependencyClass);
          }
        });
      }

      if (missingDependencies.length === 0) {
        if (debug) {
          if (Object.keys(availableDependencies).length === 0) {
            console.log('Loading', moduleClass.name);
          } else {
            console.log('Loading', moduleClass.name, 'with dependencies:', Object.keys(availableDependencies));
          }
        }
        this.modules[desiredModuleName] = new moduleClass(this, availableDependencies, Object.keys(this.modules).length);
      } else {
        debug && console.warn(moduleClass.name, 'could not be loaded, missing dependencies:', missingDependencies.map(d => d.name));
        failedModules.push(desiredModuleName);
      }
    });

    if (failedModules.length !== 0) {
      debug && console.warn(`${failedModules.length} modules failed to load, trying again:`, failedModules.map(key => modules[key].name));
      const newBatch = {};
      failedModules.forEach(key => {
        newBatch[key] = modules[key];
      });
      this.initializeModules(newBatch);
    }
  }
  findModule(type) {
    return Object.keys(this.modules)
      .map(key => this.modules[key])
      .find(module => module instanceof type);
  }

  _debugEventHistory = [];
  parseEvents(events) {
    if (process.env.NODE_ENV === 'development') {
      this._debugEventHistory = [
        ...this._debugEventHistory,
        ...events,
      ];
    }
    return new Promise((resolve, reject) => {
      events.forEach(event => {
        if (this.error) {
          throw new Error(this.error);
        }
        this._timestamp = event.timestamp;

        // Triggering a lot of events here for development pleasure; does this have a significant performance impact?
        this.triggerEvent(event.type, event);
      });

      resolve(events.length);
    });
  }
  triggerEvent(eventType, event, ...args) {
    this.activeModules
      .sort((a, b) => a.priority - b.priority) // lowest should go first, as `priority = 0` will have highest prio
      .forEach(module => {
        module.triggerEvent('event', event, ...args);
        module.triggerEvent(eventType, event, ...args);
        if (event && this.byPlayer(event)) {
          module.triggerEvent(`byPlayer_${eventType}`, event, ...args);
        }
        if (event && this.toPlayer(event)) {
          module.triggerEvent(`toPlayer_${eventType}`, event, ...args);
        }
      });
  }

  byPlayer(event, playerId = this.player.id) {
    return (event.sourceID === playerId);
  }
  toPlayer(event, playerId = this.player.id) {
    return (event.targetID === playerId);
  }

  // TODO: Damage taken from LOTM

  getPercentageOfTotalHealingDone(healingDone) {
    return healingDone / this.modules.healingDone.total.effective;
  }
  formatItemHealingDone(healingDone) {
    return `${formatPercentage(this.getPercentageOfTotalHealingDone(healingDone))} % / ${formatNumber(healingDone / this.fightDuration * 1000)} HPS`;
  }
  formatItemAbsorbDone(absorbDone) {
    return `${formatNumber(absorbDone)}`;
  }
  getPercentageOfTotalDamageDone(damageDone) {
    return damageDone / this.modules.damageDone.total.effective;
  }
  formatItemDamageDone(damageDone) {
    return `${formatPercentage(this.getPercentageOfTotalDamageDone(damageDone))} % / ${formatNumber(damageDone / this.fightDuration * 1000)} DPS`;
  }

  generateResults() {
    const results = new ParseResults();

    this.activeModules
      .sort((a, b) => b.priority - a.priority)
      .forEach(module => {
        if (module.statistic) {
          const statistic = module.statistic();
          if (statistic) {
            results.statistics.push({
              statistic,
              order: module.statisticOrder,
            });
          }
        }
        if (module.item) {
          const item = module.item();
          if (item) {
            results.items.push(item);
          }
        }
        if (module.tab) {
          const tab = module.tab();
          if (tab) {
            results.tabs.push(tab);
          }
        }
        if (module.suggestions) {
          module.suggestions(results.suggestions.when);
        }
      });

    return results;
  }
}

export default CombatLogParser;
<|endoftext|>


<commit_before>// Ionic Geofence example App

angular.module('breadcrumb', [
  'ionic',
  'ionic.contrib.ui.tinderCards',
  'leaflet-directive',
  'auth0',
  'angular-storage',
  'angular-jwt',
])
.run(function (
  $window,
  $document,
  $ionicLoading,
  $state,
  $ionicPlatform,
  $log,
  $rootScope,
  GeofencePluginMock,
  auth,
  store
) {
  $ionicPlatform.ready(function () {
    $rootScope.pinged = false;
    // $log.log('Ionic ready');
    // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
    // for form inputs)
    if ($window.cordova && $window.cordova.plugins.Keyboard) {
      $window.cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
    }
    if ($window.StatusBar) {
      $window.StatusBar.styleDefault();
    }
    if ($window.geofence === undefined) {
      // $log.warn('Geofence Plugin not found. Using mock instead.');
      $window.geofence = GeofencePluginMock;
      $window.TransitionType = GeofencePluginMock.TransitionType;
    }
    if (navigator.splashscreen) {
      navigator.splashscreen.hide();
    }

    $window.geofence.onTransitionReceived = (geofences) => {
      $log.log(geofences);
      if (geofences) {
        $rootScope.$apply(() => {
          geofences.forEach((geo) => {
            geo.notification = geo.notification || {
              title: 'Geofence transition',
              text: 'Without notification',
            };
            $rootScope.pinged = true;
          });
        });
      }
    };

    $window.geofence.onNotificationClicked = (notificationData) => {
      $log.log(notificationData);

      if (notificationData) {
        $rootScope.$apply(() => {
          $ionicLoading.show({
            template: `Notification clicked: ${notificationData.notification.text}`,
            noBackdrop: true,
            duration: 2000,
          });

          $state.go('geofence', {
            geofenceId: notificationData.id,
          });
        });
      }
    };

    $window.geofence.initialize(() => {
      $log.log('Geofence plugin initialized');
    });

    $rootScope.$on('$locationChangeStart', () => {
      if (!auth.isAuthenticated) {
        const token = store.get('token');
        if (token) {
          auth.authenticate(store.get('profile'), token);
        }
      }
    });
  });
})
.controller('AppCtrl', function ($scope, auth, store, $state) {
  $scope.logout = () => {
    auth.signout();
    store.remove('token');
    store.remove('profile');
    store.remove('refreshToken');
    $state.go('start', {}, { reload: true });
  };

  $scope.test = (input) => {
    console.warn(input);
  };

  $scope.setTrail = (id) => {
    localStorage.setItem('trail', id);
  };

  // $scope.user = JSON.parse(localStorage.user).username;

  $scope.overflowStyle = {
    'max-height': '100px',
    overflow: 'scroll',
  };
});
<commit_msg>(cleanup) comment out ionic.loading<commit_after>// Ionic Geofence example App

angular.module('breadcrumb', [
  'ionic',
  'ionic.contrib.ui.tinderCards',
  'leaflet-directive',
  'auth0',
  'angular-storage',
  'angular-jwt',
])
.run(function (
  $window,
  $document,
  $ionicLoading,
  $state,
  $ionicPlatform,
  $log,
  $rootScope,
  GeofencePluginMock,
  auth,
  store
) {
  $ionicPlatform.ready(function () {
    $log.log('Ionic ready');
    // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
    // for form inputs)
    if ($window.cordova && $window.cordova.plugins.Keyboard) {
      $window.cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
    }
    if ($window.StatusBar) {
      $window.StatusBar.styleDefault();
    }
    if ($window.geofence === undefined) {
      $log.warn('Geofence Plugin not found. Using mock instead.');
      $window.geofence = GeofencePluginMock;
      $window.TransitionType = GeofencePluginMock.TransitionType;
    }
    if (navigator.splashscreen) {
      navigator.splashscreen.hide();
    }

    $window.geofence.onTransitionReceived = (geofences) => {
      $log.log(geofences);
      if (geofences) {
        $rootScope.$apply(() => {
          geofences.forEach((geo) => {
            geo.notification = geo.notification || {
              title: 'Geofence transition',
              text: 'Without notification',
            };
            // $ionicLoading.show({
            //   template: `${geo.notification.title}: ${geo.notification.text}`,
            //   noBackdrop: true,
            //   duration: 2000,
            // });
          });
        });
      }
    };

    $window.geofence.onNotificationClicked = (notificationData) => {
      $log.log(notificationData);

      if (notificationData) {
        $rootScope.$apply(() => {
          $ionicLoading.show({
            template: `Notification clicked: ${notificationData.notification.text}`,
            noBackdrop: true,
            duration: 2000,
          });

          $state.go('geofence', {
            geofenceId: notificationData.id,
          });
        });
      }
    };

    $window.geofence.initialize(() => {
      $log.log('Geofence plugin initialized');
    });

    $rootScope.$on('$locationChangeStart', () => {
      if (!auth.isAuthenticated) {
        const token = store.get('token');
        if (token) {
          auth.authenticate(store.get('profile'), token);
        }
      }
    });
  });
})
.controller('AppCtrl', function ($scope, auth, store, $state) {
  $scope.logout = () => {
    auth.signout();
    store.remove('token');
    store.remove('profile');
    store.remove('refreshToken');
    $state.go('start', {}, { reload: true });
  };

  $scope.test = (input) => {
    console.warn(input);
  };

  $scope.setTrail = (id) => {
    localStorage.setItem('trail', id);
  };

  // $scope.user = JSON.parse(localStorage.user).username;

  $scope.overflowStyle = {
    'max-height': '125px',
    overflow: 'scroll',
  };
});
<|endoftext|>


<commit_before>import fetch from 'isomorphic-fetch';
import config from '../client-config';

export default class ApiClient {
  /**
   * @param {Hapi Request} (optional) the request the server received for a full
   *        server-rendered page. The request may include cookies or other user
   *        identifying information to correctly make API calls on behalf of
   *        the requesting user
   */
  constructor(serverReq) {
    this.cookies = {
      headers: {}
    };

    if (__SERVER__) {
      // console.log(serverReq);
      // this.cookies = ...
      // TODO: Make cookies go through when rendering server side
    }
  }

  get(path) {
    const options = {
      ...this.cookies
    };
    return this.performFetch(path, options);
  }

  post(path, data) {
    const options = {
      ...this.cookies,
      method: 'post',
      body: JSON.stringify(data)
    };
    options.headers['Accept'] = 'application/json'; // eslint-disable-line dot-notation
    options.headers['Content-Type'] = 'application/json';

    return this.performFetch(path, options);
  }

  delete(path) {
    const options = {
      ...this.cookies,
      method: 'delete'
    };
    return this.performFetch(path, options);
  }

  performFetch(path, options) {
    const url = this.formatUrl(path);
    return fetch(url, options).then((data) => {
      return data.json();
    });
  }

  formatUrl(path) {
    const adjustedPath = path[0] !== '/' ? '/' + path : path;
    return config.apiPath + adjustedPath;
  }
}
<commit_msg>Forward client cookies on universal server rendering proxy calls<commit_after>import fetch from 'isomorphic-fetch';
import config from '../client-config';

export default class ApiClient {
  /**
   * @param {Hapi Request} (optional) the request the server received for a full
   *        server-rendered page. The request may include cookies or other user
   *        identifying information to correctly make API calls on behalf of
   *        the requesting user
   */
  constructor(serverReq) {
    this.defaultOptions = {
      credentials: 'same-origin',
      headers: {}
    };

    if (__SERVER__) {
      // If we're executing a server-side fetch on behalf of the user for universal
      // rendering, we need to forward along the cookies.
      this.defaultOptions.headers.cookie = serverReq.headers.cookie;
    }
  }

  get(path) {
    const options = {
      ...this.defaultOptions
    };

    return this.performFetch(path, options);
  }

  post(path, data) {
    const options = {
      ...this.defaultOptions,
      method: 'post',
      body: JSON.stringify(data)
    };
    options.headers['Accept'] = 'application/json'; // eslint-disable-line dot-notation
    options.headers['Content-Type'] = 'application/json';

    return this.performFetch(path, options);
  }

  delete(path) {
    const options = {
      ...this.defaultOptions,
      method: 'delete'
    };

    return this.performFetch(path, options);
  }

  performFetch(path, options) {
    const url = this.formatUrl(path);
    return fetch(url, options).then((data) => {
      return data.json();
    });
  }

  formatUrl(path) {
    const adjustedPath = path[0] !== '/' ? '/' + path : path;
    return config.apiPath + adjustedPath;
  }
}
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2015 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// TODO: Add datalist support.

foam.CLASS({
  package: 'foam.u2',
  name: 'DateView',
  extends: 'foam.u2.tag.Input',

  documentation: 'View for editing Date values.',

  css: '^:read-only { border: none; background: rgba(0,0,0,0); }',

  axioms: [
    { class: 'foam.u2.TextInputCSS' }
  ],

  properties: [
    [ 'placeholder', 'yyyy-mm-dd' ]
  ],

  listeners: [
    {
      name: 'onBlur',
      isFramed: true,
      code: function() {
        if ( ! this.el() ) return;
        this.el().value = this.dataToInput(this.data);
      }
    }
  ],

  methods: [
    function initE() {
      this.SUPER();
      this.setAttribute('type', 'date');
      this.setAttribute('max', '9999-12-31');
      this.setAttribute('placeholder', 'yyyy/mm/dd');
      this.on('blur', this.onBlur);
    },

    function link() {
      this.data$.relateTo(
          this.attrSlot(null, this.onKey ? 'input' : null),
          d => this.dataToInput(d),
          d => this.inputToData(d)
      );
    },

    function inputToData(input) {
      var d = new Date(input);
      return isNaN(d.getTime()) ? null : d;
    },

    function dataToInput(data) {
      if ( ! data ) return data;

      // Using our own formatter to keep the date in the format (yyyy-mm-dd) while maintaining the locale date
      const year = data.getUTCFullYear();
      const month = (data.getUTCMonth() + 1).toString().padStart(2, '0');
      const day = data.getUTCDate().toString().padStart(2, '0');

      return `${year}-${month}-${day}`;
    }
  ]
});
<commit_msg>Date view safari fix, check for data value prior to resolving date<commit_after>/**
 * @license
 * Copyright 2015 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// TODO: Add datalist support.

foam.CLASS({
  package: 'foam.u2',
  name: 'DateView',
  extends: 'foam.u2.tag.Input',

  documentation: 'View for editing Date values.',

  css: '^:read-only { border: none; background: rgba(0,0,0,0); }',

  axioms: [
    { class: 'foam.u2.TextInputCSS' }
  ],

  properties: [
    [ 'placeholder', 'yyyy-mm-dd' ]
  ],

  listeners: [
    {
      name: 'onBlur',
      isFramed: true,
      code: function() {
        if ( ! this.el() || ! this.data ) return;
        this.el().value = this.dataToInput(this.data);
      }
    }
  ],

  methods: [
    function initE() {
      this.SUPER();
      this.setAttribute('type', 'date');
      this.setAttribute('max', '9999-12-31');
      this.setAttribute('placeholder', 'yyyy/mm/dd');
      this.on('blur', this.onBlur);
    },

    function link() {
      this.data$.relateTo(
          this.attrSlot(null, this.onKey ? 'input' : null),
          d => this.dataToInput(d),
          d => this.inputToData(d)
      );
    },

    function inputToData(input) {
      var d = new Date(input);
      return isNaN(d.getTime()) ? null : d;
    },

    function dataToInput(data) {
      if ( ! data ) return data;

      // Using our own formatter to keep the date in the format (yyyy-mm-dd) while maintaining the locale date
      const year = data.getUTCFullYear();
      const month = (data.getUTCMonth() + 1).toString().padStart(2, '0');
      const day = data.getUTCDate().toString().padStart(2, '0');

      return `${year}-${month}-${day}`;
    }
  ]
});
<|endoftext|>


<commit_before>import _ from 'underscore';
import crypto from 'crypto';
import fs from 'fs';
import path from 'path';
import request from 'request';
import progress from 'request-progress';
import Promise from 'bluebird';
import util from './Util';
import resources from './ResourcesUtil';
var virtualBox = require ('./VirtualBoxUtil');

var SetupUtil = {
  needsBinaryFix() {
    return this.pathDoesNotExistOrDenied(util.binsPath()) ||
        (fs.existsSync(util.dockerBinPath()) && this.pathDenied(util.dockerBinPath())) ||
        (fs.existsSync(util.dockerMachineBinPath()) && this.pathDenied(util.dockerMachineBinPath()));
  },
  pathDoesNotExistOrDenied: function (path) {
    if(util.isWindows()) {
      return (!fs.existsSync(path));
    } else {
      return (!fs.existsSync(path) || this.pathDenied(path));
    }
  },
  pathDenied: function (path) {
    return fs.statSync(path).gid !== 80 || fs.statSync(path).uid !== process.getuid();
  },
  shouldUpdateBinaries: function () {
    return !fs.existsSync(util.dockerBinPath()) ||
        !fs.existsSync(util.dockerMachineBinPath()) ||
        !fs.existsSync(util.dockerComposeBinPath()) ||
        this.checksum(util.dockerBinPath()) !== this.checksum(resources.docker()) ||
        this.checksum(util.dockerMachineBinPath()) !== this.checksum(resources.dockerMachine()) ||
        this.checksum(util.dockerComposeBinPath()) !== this.checksum(resources.dockerCompose());
  },
  copycmd: function (src, dest) {
    return ['rm', '-f', dest, '&&', 'cp', src, dest];
  },
  copyBinariesCmd: function () {
    var cmd = ['mkdir', '-p', '/usr/local/bin'];
    cmd.push('&&');
    cmd.push.apply(cmd, this.copycmd(util.escapePath(resources.dockerMachine()), '/usr/local/bin/docker-machine'));
    cmd.push('&&');
    cmd.push.apply(cmd, this.copycmd(util.escapePath(resources.docker()), '/usr/local/bin/docker'));
    cmd.push('&&');
    cmd.push.apply(cmd, this.copycmd(util.escapePath(resources.dockerCompose()), '/usr/local/bin/docker-compose'));
    return cmd.join(' ');
  },
  fixBinariesCmd: function () {
    var cmd = [];
    cmd.push.apply(cmd, ['chown', `${process.getuid()}:${80}`, path.join('/usr/local/bin')]);
    cmd.push('&&');
    cmd.push.apply(cmd, ['chown', `${process.getuid()}:${80}`, path.join('/usr/local/bin', 'docker-machine')]);
    cmd.push('&&');
    cmd.push.apply(cmd, ['chown', `${process.getuid()}:${80}`, path.join('/usr/local/bin', 'docker')]);
    cmd.push('&&');
    cmd.push.apply(cmd, ['chown', `${process.getuid()}:${80}`, path.join('/usr/local/bin', 'docker-compose')]);
    return cmd.join(' ');
  },
  installVirtualBoxCmd: function () {
    if(util.isWindows()) {
      return `powershell.exe -ExecutionPolicy unrestricted -Command "ls"`;
    } else {
      return `installer -pkg ${util.escapePath(path.join(util.supportDir(), virtualBox.filename()))} -target /`;
    }
  },
  macSudoCmd: function (cmd) {
    return `${util.escapePath(resources.macsudo())} -p "Kitematic requires administrative privileges to install and/or start VirtualBox." sh -c \"${cmd}\"`;
  },
  simulateProgress(estimateSeconds, progress) {
    var times = _.range(0, estimateSeconds * 1000, 200);
    var timers = [];
    _.each(times, time => {
      var timer = setTimeout(() => {
        progress(100 * time / (estimateSeconds * 1000));
      }, time);
      timers.push(timer);
    });
  },
  checksum(filename) {
    return crypto.createHash('sha256').update(fs.readFileSync(filename), 'utf8').digest('hex');
  },
  download(url, filename, checksum, percentCallback) {
    return new Promise((resolve, reject) => {
      if (fs.existsSync(filename)) {
        var existingChecksum = this.checksum(filename);
        if (existingChecksum === checksum) {
          resolve();
          return;
        } else {
          fs.unlinkSync(filename);
        }
      }

      progress(request({ uri: url, rejectUnauthorized: false }), { throttle: 10 }).on('progress', state => {
        if (percentCallback) {
          percentCallback(state.percent);
        }
      }).on('error', err => {
        reject(err);
      }).pipe(fs.createWriteStream(filename)).on('error', err => {
        reject(err);
      }).on('close', err => {
        if (err) {
          reject(err);
        }
        resolve();
      });
    });
  }
};

module.exports = SetupUtil;
<commit_msg>Changing so always detects Virtual Box<commit_after>import _ from 'underscore';
import crypto from 'crypto';
import fs from 'fs';
import path from 'path';
import request from 'request';
import progress from 'request-progress';
import Promise from 'bluebird';
import util from './Util';
import resources from './ResourcesUtil';
var virtualBox = require ('./VirtualBoxUtil');

var SetupUtil = {
  needsBinaryFix() {
    return this.pathDoesNotExistOrDenied(util.binsPath()) ||
        (fs.existsSync(util.dockerBinPath()) && this.pathDenied(util.dockerBinPath())) ||
        (fs.existsSync(util.dockerMachineBinPath()) && this.pathDenied(util.dockerMachineBinPath()));
  },
  pathDoesNotExistOrDenied: function (path) {
    if(util.isWindows()) {
      return (fs.existsSync(path));
    } else {
      return (!fs.existsSync(path) || this.pathDenied(path));
    }
  },
  pathDenied: function (path) {
    return fs.statSync(path).gid !== 80 || fs.statSync(path).uid !== process.getuid();
  },
  shouldUpdateBinaries: function () {
    return !fs.existsSync(util.dockerBinPath()) ||
        !fs.existsSync(util.dockerMachineBinPath()) ||
        !fs.existsSync(util.dockerComposeBinPath()) ||
        this.checksum(util.dockerBinPath()) !== this.checksum(resources.docker()) ||
        this.checksum(util.dockerMachineBinPath()) !== this.checksum(resources.dockerMachine()) ||
        this.checksum(util.dockerComposeBinPath()) !== this.checksum(resources.dockerCompose());
  },
  copycmd: function (src, dest) {
    return ['rm', '-f', dest, '&&', 'cp', src, dest];
  },
  copyBinariesCmd: function () {
    var cmd = ['mkdir', '-p', '/usr/local/bin'];
    cmd.push('&&');
    cmd.push.apply(cmd, this.copycmd(util.escapePath(resources.dockerMachine()), '/usr/local/bin/docker-machine'));
    cmd.push('&&');
    cmd.push.apply(cmd, this.copycmd(util.escapePath(resources.docker()), '/usr/local/bin/docker'));
    cmd.push('&&');
    cmd.push.apply(cmd, this.copycmd(util.escapePath(resources.dockerCompose()), '/usr/local/bin/docker-compose'));
    return cmd.join(' ');
  },
  fixBinariesCmd: function () {
    var cmd = [];
    cmd.push.apply(cmd, ['chown', `${process.getuid()}:${80}`, path.join('/usr/local/bin')]);
    cmd.push('&&');
    cmd.push.apply(cmd, ['chown', `${process.getuid()}:${80}`, path.join('/usr/local/bin', 'docker-machine')]);
    cmd.push('&&');
    cmd.push.apply(cmd, ['chown', `${process.getuid()}:${80}`, path.join('/usr/local/bin', 'docker')]);
    cmd.push('&&');
    cmd.push.apply(cmd, ['chown', `${process.getuid()}:${80}`, path.join('/usr/local/bin', 'docker-compose')]);
    return cmd.join(' ');
  },
  installVirtualBoxCmd: function () {
    if(util.isWindows()) {
      return `powershell.exe -ExecutionPolicy unrestricted -Command "ls"`;
    } else {
      return `installer -pkg ${util.escapePath(path.join(util.supportDir(), virtualBox.filename()))} -target /`;
    }
  },
  macSudoCmd: function (cmd) {
    return `${util.escapePath(resources.macsudo())} -p "Kitematic requires administrative privileges to install and/or start VirtualBox." sh -c \"${cmd}\"`;
  },
  simulateProgress(estimateSeconds, progress) {
    var times = _.range(0, estimateSeconds * 1000, 200);
    var timers = [];
    _.each(times, time => {
      var timer = setTimeout(() => {
        progress(100 * time / (estimateSeconds * 1000));
      }, time);
      timers.push(timer);
    });
  },
  checksum(filename) {
    return crypto.createHash('sha256').update(fs.readFileSync(filename), 'utf8').digest('hex');
  },
  download(url, filename, checksum, percentCallback) {
    return new Promise((resolve, reject) => {
      if (fs.existsSync(filename)) {
        var existingChecksum = this.checksum(filename);
        if (existingChecksum === checksum) {
          resolve();
          return;
        } else {
          fs.unlinkSync(filename);
        }
      }

      progress(request({ uri: url, rejectUnauthorized: false }), { throttle: 10 }).on('progress', state => {
        if (percentCallback) {
          percentCallback(state.percent);
        }
      }).on('error', err => {
        reject(err);
      }).pipe(fs.createWriteStream(filename)).on('error', err => {
        reject(err);
      }).on('close', err => {
        if (err) {
          reject(err);
        }
        resolve();
      });
    });
  }
};

module.exports = SetupUtil;
<|endoftext|>