<commit_before>var SNKit = (() => {
  return {
    version: "2.0.0",
    getWidgetDetails: (callback) => {
      var details = [];
      var spWidgets = document.querySelectorAll("[widget='widget']");

      spWidgets.forEach((w, i) => {
        var detailObj = {};
        var thisScope = angular.element(spWidgets[i]).scope();
        detailObj.name = thisScope.widget.name;
        detailObj.technicalName = thisScope.widget.id;
        detailObj.id = spWidgets[i].id
        detailObj.className = spWidgets[i].classList.item(0);
        detailObj.identifier = "class"
        detailObj.portalId = thisScope.portal.sys_id;
        detailObj.themeId = thisScope.theme.sys_id;
        detailObj.pageId = thisScope.page.sys_id;
        detailObj.serverTime = thisScope.widget._server_time;
        if(thisScope.theme.header && thisScope.theme.header.sys_id) detailObj.headerId = thisScope.theme.header.sys_id;
        if(thisScope.theme.footer && thisScope.theme.footer.sys_id) detailObj.footerId = thisScope.theme.footer.sys_id;
        details.push(detailObj);
      })
      callback(details);
    },
    getWidgetScopes: (p1, p2) => {
      var _widgetName;
      var _callback;
      /**
       * Allow the user to either enter a string name of the widget, a string name of
       * the widget with a callback, or just a callback.
       */
      if(p1) {
        if(typeof(p1) === "string") {
          _widgetName = p1;
        } else if(typeof(p1) === "function") {
          _callback = p1;
        }
      }
      if(p2) {
        if(typeof(p2) === "function")
          _callback = p2;
      }

      var widgetScopes = [];
      var spWidgets = document.querySelectorAll("[widget='widget']");

      spWidgets.forEach((widget, i) => {
        var thisScope = angular.element(spWidgets[i]).scope();
        widgetScopes.push(thisScope);
      });

      if(_widgetName) {
        if (_callback) {
          var results = widgetScopes.filter((scope) => {
            return scope.widget.name.toUpperCase() == _widgetName.toUpperCase()
          });
          _callback(results);
          return;
        } else {
          return widgetScopes.filter((scope) => {
            return scope.widget.name.toUpperCase() == _widgetName.toUpperCase()
          });
        }
      }
      if(_callback) _callback(widgetScopes);
      else return widgetScopes;
    },
    timeServer: (scope) => {

      return new Promise((resolve, reject) => {
        var timing;
        var start = Date.now();
        //console.log(scope.widget.name + " started @" + Date.now());
        scope.server.refresh().then(() => {
          var end = Date.now();
          //console.log(scope.widget.name + " finished @" + Date.now());
          timing = end - start;

          //record timing in widget scope
          scope.load_time = timing;

          resolve({timing: timing, name: scope.widget.name});
        });
      });
    },
    // Promises need to run in a synchronous chain, this is not happening yet.
    getServerTimings: (callback) => {
      var scopes = SNKit.getWidgetScopes();
      var timingResults = [];
      var chain = Promise.resolve();
      scopes.forEach((scope, i, a) => {
        chain = chain.then(() =>
          SNKit.timeServer(scope)).then((result) => {
            timingResults.push(result)
            // if this is the last element in the array, then send the information back
            if(i == (a.length - 1)){
              callback(timingResults);
            }
          });
      });
    },
    isServicePortalPage: (callback) => {
      callback(window.NOW.hasOwnProperty("sp"));
    },
    getHostName: (callback) => {
      callback(window.location.hostname);
    }
  }
})();

var snkit_api = (() => {
  return {
    widgetsToConsole: () => {
      var widgetScopes = SNKit.getWidgetScopes();
      var names = [];
      var duplicateWidgetCounter = {};
      widgetScopes.forEach((scope) => {
        var scriptableName = `$${scope.widget.name.toLowerCase()}`;
        scriptableName = scriptableName.split(" ").join("_");
        //check for duplicates and tag them with numbers
        if(names.indexOf(scriptableName) !== -1){
          if(duplicateWidgetCounter.hasOwnProperty(scriptableName)){
            duplicateWidgetCounter[scriptableName]++;
            scriptableName = scriptableName + duplicateWidgetCounter[scriptableName];
          } else {
            duplicateWidgetCounter[scriptableName] = 1;
            scriptableName = scriptableName + duplicateWidgetCounter[scriptableName];
          }
        } else {
          names.push(scriptableName);
        }
        snkit_api[scriptableName] = scope;
      });
    },
    getGlideForm: () => {
      snkit_api.g_form = angular.element("sp-variable-layout").scope().getGlideForm();
    },
    getService: (serviceName) => {
      snkit_api[serviceName] = angular.element(document.querySelector("[ng-app]")).injector().get(serviceName);
    }
  }
})();

window.addEventListener("snkitRequest", function(event) {
  var cmd = event.detail.cmd;
  var cmdData = event.detail.cmdData;
  if (cmd === "getWidgetDetails"){
    SNKit.getWidgetDetails((data) => {
      // send the data back to the content script
      window.postMessage({ type: "from_page", text: data, cmd: cmd }, "*");
    });
  } else if (cmd === "isServicePortalPage"){
    SNKit.isServicePortalPage((data) => {
      // send the data back to the content script
      window.postMessage({ type: "from_page", text: data, cmd: cmd }, "*");
    });
  } else if (cmd === "getHostName"){
    SNKit.getHostName((data) => {
      // send the data back to the content script
      window.postMessage({ type: "from_page", text: data, cmd: cmd }, "*");
    });
  } else if (cmd === "getServerTimings"){
    SNKit.getServerTimings((data) => {

      //lets log the performance data into a table in the console
      console.table(data);

      // send the data back to the content script
      window.postMessage({ type: "from_page", text: data, cmd: cmd }, "*");
    });
  }
}, false);<commit_msg>adjust scope key to ensure it's clear<commit_after>var SNKit = (() => {
  return {
    version: "2.0.0",
    getWidgetDetails: (callback) => {
      var details = [];
      var spWidgets = document.querySelectorAll("[widget='widget']");

      spWidgets.forEach((w, i) => {
        var detailObj = {};
        var thisScope = angular.element(spWidgets[i]).scope();
        detailObj.name = thisScope.widget.name;
        detailObj.technicalName = thisScope.widget.id;
        detailObj.id = spWidgets[i].id
        detailObj.className = spWidgets[i].classList.item(0);
        detailObj.identifier = "class"
        detailObj.portalId = thisScope.portal.sys_id;
        detailObj.themeId = thisScope.theme.sys_id;
        detailObj.pageId = thisScope.page.sys_id;
        detailObj.serverTime = thisScope.widget._server_time;
        if(thisScope.theme.header && thisScope.theme.header.sys_id) detailObj.headerId = thisScope.theme.header.sys_id;
        if(thisScope.theme.footer && thisScope.theme.footer.sys_id) detailObj.footerId = thisScope.theme.footer.sys_id;
        details.push(detailObj);
      })
      callback(details);
    },
    getWidgetScopes: (p1, p2) => {
      var _widgetName;
      var _callback;
      /**
       * Allow the user to either enter a string name of the widget, a string name of
       * the widget with a callback, or just a callback.
       */
      if(p1) {
        if(typeof(p1) === "string") {
          _widgetName = p1;
        } else if(typeof(p1) === "function") {
          _callback = p1;
        }
      }
      if(p2) {
        if(typeof(p2) === "function")
          _callback = p2;
      }

      var widgetScopes = [];
      var spWidgets = document.querySelectorAll("[widget='widget']");

      spWidgets.forEach((widget, i) => {
        var thisScope = angular.element(spWidgets[i]).scope();
        widgetScopes.push(thisScope);
      });

      if(_widgetName) {
        if (_callback) {
          var results = widgetScopes.filter((scope) => {
            return scope.widget.name.toUpperCase() == _widgetName.toUpperCase()
          });
          _callback(results);
          return;
        } else {
          return widgetScopes.filter((scope) => {
            return scope.widget.name.toUpperCase() == _widgetName.toUpperCase()
          });
        }
      }
      if(_callback) _callback(widgetScopes);
      else return widgetScopes;
    },
    timeServer: (scope) => {

      return new Promise((resolve, reject) => {
        var timing;
        var start = Date.now();
        //console.log(scope.widget.name + " started @" + Date.now());
        scope.server.refresh().then(() => {
          var end = Date.now();
          //console.log(scope.widget.name + " finished @" + Date.now());
          timing = end - start;

          //record timing in widget scope
          scope.snkit_load_time_ms = timing;

          resolve({timing: timing, name: scope.widget.name});
        });
      });
    },
    // Promises need to run in a synchronous chain, this is not happening yet.
    getServerTimings: (callback) => {
      var scopes = SNKit.getWidgetScopes();
      var timingResults = [];
      var chain = Promise.resolve();
      scopes.forEach((scope, i, a) => {
        chain = chain.then(() =>
          SNKit.timeServer(scope)).then((result) => {
            timingResults.push(result)
            // if this is the last element in the array, then send the information back
            if(i == (a.length - 1)){
              callback(timingResults);
            }
          });
      });
    },
    isServicePortalPage: (callback) => {
      callback(window.NOW.hasOwnProperty("sp"));
    },
    getHostName: (callback) => {
      callback(window.location.hostname);
    }
  }
})();

var snkit_api = (() => {
  return {
    widgetsToConsole: () => {
      var widgetScopes = SNKit.getWidgetScopes();
      var names = [];
      var duplicateWidgetCounter = {};
      widgetScopes.forEach((scope) => {
        var scriptableName = `$${scope.widget.name.toLowerCase()}`;
        scriptableName = scriptableName.split(" ").join("_");
        //check for duplicates and tag them with numbers
        if(names.indexOf(scriptableName) !== -1){
          if(duplicateWidgetCounter.hasOwnProperty(scriptableName)){
            duplicateWidgetCounter[scriptableName]++;
            scriptableName = scriptableName + duplicateWidgetCounter[scriptableName];
          } else {
            duplicateWidgetCounter[scriptableName] = 1;
            scriptableName = scriptableName + duplicateWidgetCounter[scriptableName];
          }
        } else {
          names.push(scriptableName);
        }
        snkit_api[scriptableName] = scope;
      });
    },
    getGlideForm: () => {
      snkit_api.g_form = angular.element("sp-variable-layout").scope().getGlideForm();
    },
    getService: (serviceName) => {
      snkit_api[serviceName] = angular.element(document.querySelector("[ng-app]")).injector().get(serviceName);
    }
  }
})();

window.addEventListener("snkitRequest", function(event) {
  var cmd = event.detail.cmd;
  var cmdData = event.detail.cmdData;
  if (cmd === "getWidgetDetails"){
    SNKit.getWidgetDetails((data) => {
      // send the data back to the content script
      window.postMessage({ type: "from_page", text: data, cmd: cmd }, "*");
    });
  } else if (cmd === "isServicePortalPage"){
    SNKit.isServicePortalPage((data) => {
      // send the data back to the content script
      window.postMessage({ type: "from_page", text: data, cmd: cmd }, "*");
    });
  } else if (cmd === "getHostName"){
    SNKit.getHostName((data) => {
      // send the data back to the content script
      window.postMessage({ type: "from_page", text: data, cmd: cmd }, "*");
    });
  } else if (cmd === "getServerTimings"){
    SNKit.getServerTimings((data) => {

      //lets log the performance data into a table in the console
      console.table(data);

      // send the data back to the content script
      window.postMessage({ type: "from_page", text: data, cmd: cmd }, "*");
    });
  }
}, false);<|endoftext|>


<commit_before>/* Magic Mirror
 * Module: MagicMirror-Sonos-Module
 *
 * By Christopher Fenner https://github.com/CFenner
 * MIT Licensed.
 */
 Module.register('sonos', {
	defaults: {
		showStoppedRoom: true,
		showAlbumArt: true,
		showRoomName: true,
		animationSpeed: 1000,
		updateInterval: 0.5, // every 0.5 minutes
		apiBase: 'http://localhost',
		apiPort: 5005,
		apiEndpoint: 'zones'
	},
	start: function() {
		Log.info('Starting module: ' + this.name);
		this.update();
		// refresh every x minutes
		setInterval(
			this.update.bind(this),
			this.config.updateInterval * 60 * 1000);
	},
	update: function(){
		this.sendSocketNotification(
			'SONOS_UPDATE',
			this.config.apiBase + ":" + this.config.apiPort + "/" + this.config.apiEndpoint);
	},
	render: function(data){
		var text = '';
		$.each(data, function (i, item) {
			var room = item.coordinator.roomName;
			var state = item.coordinator.state.zoneState;
			var artist = item.coordinator.state.currentTrack.artist;
			var track = item.coordinator.state.currentTrack.title;
			var cover = item.coordinator.state.currentTrack.absoluteAlbumArtURI;
			var streamInfo = item.coordinator.state.currentTrack.streamInfo;
			if(item.members.length > 1){
				room = '';
				$.each(item.members, function (j, member) {
					room += member.roomName + ', ';
				});
				room = room.slice(0, -2);
			}
			text += this.renderRoom(state, artist, track, cover, room);
		}.bind(this));
		this.loaded = true;
		// only update dom if content changed
		if(this.dom !== text){
			this.dom = text;
			this.updateDom(this.config.animationSpeed);
		}
	},
	renderRoom: function(state, artist, track, cover, roomName) {
		var room = '';
		// show song if PLAYING
		if(state === 'PLAYING') {
			room += this.html.song.format(
				this.html.name.format(artist, track)+
				// show album art if 'showAlbumArt' is set
				(this.config.showAlbumArt
					?this.html.art.format(cover)
					:''
				)
				//+""+streamInfo+""
			);
		}
		// show room name if 'showRoomName' is set and PLAYING or 'showStoppedRoom' is set
		if(this.config.showRoomName && (state === 'PLAYING' || this.config.showStoppedRoom)) {
			room += this.html.room.format(roomName);
		}
		return  this.html.roomWrapper.format(room);
	},
	html: {
		loading: '
Loading music ...
',
		roomWrapper: '
{0}
',
		room: '
{0}
',
		song: '
{0}
',
		name: '

{0}

{1}

',
		art: '

'
	},
	getScripts: function() {
		return [
			'String.format.js',
			'//cdnjs.cloudflare.com/ajax/libs/jquery/2.2.2/jquery.js'
		];
	},
	getStyles: function() {
		return ['sonos.css'];
	},
	getDom: function() {
		var content = '';
		if (!this.loaded) {
			content = this.html.loading;
		}else if(this.data.position.endsWith("left")){
			content = '
'+this.dom+'
';
		}else{
			content = '
'+this.dom+'
';
		}
		return $('
'+content+'
')[0];
	},
  socketNotificationReceived: function(notification, payload) {
      if (notification === 'SONOS_DATA') {
          Log.info('received SONOS_DATA');
					this.render(payload);
      }
  }
});
<commit_msg>hide playing speakers with no track information<commit_after>/* Magic Mirror
 * Module: MagicMirror-Sonos-Module
 *
 * By Christopher Fenner https://github.com/CFenner
 * MIT Licensed.
 */
 Module.register('sonos', {
	defaults: {
		showStoppedRoom: true,
		showAlbumArt: true,
		showRoomName: true,
		animationSpeed: 1000,
		updateInterval: 0.5, // every 0.5 minutes
		apiBase: 'http://localhost',
		apiPort: 5005,
		apiEndpoint: 'zones'
	},
	start: function() {
		Log.info('Starting module: ' + this.name);
		this.update();
		// refresh every x minutes
		setInterval(
			this.update.bind(this),
			this.config.updateInterval * 60 * 1000);
	},
	update: function(){
		this.sendSocketNotification(
			'SONOS_UPDATE',
			this.config.apiBase + ":" + this.config.apiPort + "/" + this.config.apiEndpoint);
	},
	render: function(data){
		var text = '';
		$.each(data, function (i, item) {
			var room = item.coordinator.roomName;
			var state = item.coordinator.state.zoneState;
			var artist = item.coordinator.state.currentTrack.artist;
			var track = item.coordinator.state.currentTrack.title;
			var cover = item.coordinator.state.currentTrack.absoluteAlbumArtURI;
			var streamInfo = item.coordinator.state.currentTrack.streamInfo;
			if(item.members.length > 1){
				room = '';
				$.each(item.members, function (j, member) {
					room += member.roomName + ', ';
				});
				room = room.slice(0, -2);
			}
			text += this.renderRoom(state, artist, track, cover, room);
		}.bind(this));
		this.loaded = true;
		// only update dom if content changed
		if(this.dom !== text){
			this.dom = text;
			this.updateDom(this.config.animationSpeed);
		}
	},
	renderRoom: function(state, artist, track, cover, roomName) {
		var room = '';
		// if Sonos Playbar is in TV mode, no title is provided and therefore the room should not be displayed
		var isEmpty = (artist && artist.trim().length) == 0
			&& (track && track.trim().length) == 0
			&& (cover && cover.trim().length) == 0;
		// show song if PLAYING
		if(state === 'PLAYING' && !isEmpty) {
			room += this.html.song.format(
				this.html.name.format(artist, track)+
				// show album art if 'showAlbumArt' is set
				(this.config.showAlbumArt
					?this.html.art.format(cover)
					:''
				)
				//+""+streamInfo+""
			);
		}
		// show room name if 'showRoomName' is set and PLAYING or 'showStoppedRoom' is set
		if(this.config.showRoomName && (state === 'PLAYING' || this.config.showStoppedRoom)) {
			room += this.html.room.format(roomName);
		}
		return  this.html.roomWrapper.format(room);
	},
	html: {
		loading: '
Loading music ...
',
		roomWrapper: '
{0}
',
		room: '
{0}
',
		song: '
{0}
',
		name: '

{0}

{1}

',
		art: '

'
	},
	getScripts: function() {
		return [
			'String.format.js',
			'//cdnjs.cloudflare.com/ajax/libs/jquery/2.2.2/jquery.js'
		];
	},
	getStyles: function() {
		return ['sonos.css'];
	},
	getDom: function() {
		var content = '';
		if (!this.loaded) {
			content = this.html.loading;
		}else if(this.data.position.endsWith("left")){
			content = '
'+this.dom+'
';
		}else{
			content = '
'+this.dom+'
';
		}
		return $('
'+content+'
')[0];
	},
  socketNotificationReceived: function(notification, payload) {
      if (notification === 'SONOS_DATA') {
          Log.info('received SONOS_DATA');
					this.render(payload);
      }
  }
});
<|endoftext|>


<commit_before>
'use strict';

(function() {

var global = this;

// Array.isArray Polyfill
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray

if (!Array.isArray) {
  Array.isArray = function(arg) {
    return Object.prototype.toString.call(arg) === '[object Array]';
  };
}

// Check if browser is IE8 or lower

var isIE8 = (function () {
    return (global.attachEvent && !global.addEventListener);
})();

// Get supported calc() prefix

var calc = (function () {
    var prefixes = ["", "-webkit-", "-moz-", "-o-"], el

    for (var i = 0; i < prefixes.length; i++) {
        el = document.createElement('div');
        el.style.cssText = "width:" + prefixes[i] + "calc(9px)";

        if (el.style.length) {
            return prefixes[i] + "calc"
        }
    }
})();

var Split = function (ids, options) {
    // Set defaults

    options = typeof options !== 'undefined' ?  options : {};

    if (!options.gutterSize) options.gutterSize = 10;
    if (!options.minSize) options.minSize = 100;
    if (!options.snapOffset) options.snapOffset = 30;
    if (!options.direction) options.direction = 'horizontal';

    // Event listeners for drag events, bound to a pair object.
    // Save the pair's position and size when dragging starts.
    // Prevent selection on start and re-enable it when done.

    var startDragging = function (e) {
            e.preventDefault();

            this.dragging = true;

            // The first and last pairs have 1.5x gutter (1 in the middle and 1/2 on the side).
            // All other pairs have 2x gutter (1 in the middle and 1/2 on each side).
            // Special case for pairs that are first and last (only 1 pair).

            if (this.isFirst && this.isLast) {
                gutterSize = options.gutterSize;
            } else if (this.isFirst || this.isLast) {
                gutterSize = options.gutterSize * 1.5;
            } else {
                gutterSize = options.gutterSize * 2;
            }

            // Calculate the pairs size, and percentage of the parent size

            if (this.direction == 'horizontal') {
                this.size = this.a.getBoundingClientRect().width + this.b.getBoundingClientRect().width + gutterSize;
                this.percentage = Math.min(this.size / this.parent.clientWidth * 100, 100);
                this.start = this.a.getBoundingClientRect().left;
            } else if (this.direction == 'vertical') {
                this.size = this.a.getBoundingClientRect().height + this.b.getBoundingClientRect().height + gutterSize;
                this.percentage = Math.min(this.size / this.parent.clientHeight * 100, 100);
                this.start = this.a.getBoundingClientRect().top;
            }

            this.a.addEventListener('selectstart', preventSelection);
            this.a.addEventListener('dragstart', preventSelection);
            this.b.addEventListener('selectstart', preventSelection);
            this.b.addEventListener('dragstart', preventSelection);

            this.a.style.userSelect = 'none';
            this.a.style.webkitUserSelect = 'none';
            this.a.style.MozUserSelect = 'none';

            this.b.style.userSelect = 'none';
            this.b.style.webkitUserSelect = 'none';
            this.b.style.MozUserSelect = 'none';

            if (options.onDragStart) {
                options.onDragStart();
            }
        },

        stopDragging = function () {
            this.dragging = false;

            this.a.removeEventListener('selectstart', preventSelection);
            this.a.removeEventListener('dragstart', preventSelection);
            this.b.removeEventListener('selectstart', preventSelection);
            this.b.removeEventListener('dragstart', preventSelection);

            this.a.style.userSelect = '';
            this.a.style.webkitUserSelect = '';
            this.a.style.MozUserSelect = '';

            this.b.style.userSelect = '';
            this.b.style.webkitUserSelect = '';
            this.b.style.MozUserSelect = '';

            if (options.onDragEnd) {
                options.onDragEnd();
            }
        },

        drag = function (e) {
            if (!this.dragging) return;

            // Get the relative position of the event from the first side of the
            // pair.

            if (this.direction == 'horizontal') {
                var offset = e.clientX - this.start;
            } else if (this.direction == 'vertical') {
                var offset = e.clientY - this.start;
            }

            // If within snapOffset of min or max, set offset to min or max

            if (offset <=  this.aMin + options.snapOffset) {
                offset = this.aMin;
            } else if (offset >= this.size - this.bMin - options.snapOffset) {
                offset = this.size - this.bMin;
            }

            // For first and last pairs, first and last gutter width is half.

            var aGutterSize = options.gutterSize;
            var bGutterSize = options.gutterSize;

            if (this.isFirst) {
                aGutterSize = options.gutterSize / 2;
            }

            if (this.isLast) {
                bGutterSize = options.gutterSize / 2;
            }

            // A size is the same as offset. B size is total size - A size.
            // Both sizes are calculated from the initial parent percentage.

            var aSize = calc + '(' + (offset / this.size * this.percentage) + '% - ' + aGutterSize + 'px)';
            var bSize = calc + '(' + (this.percentage - (offset / this.size * this.percentage)) + '% - ' + bGutterSize + 'px)';

            if (this.direction == 'horizontal') {
                this.a.style.width = aSize;
                this.b.style.width = bSize;
            } else if (this.direction == 'vertical') {
                this.a.style.height = aSize;
                this.b.style.height = bSize;
            }

            if (options.onDrag) {
                options.onDrag();
            }
        },

        preventSelection = function () { return false; },

        // Given a list of DOM element ids and a list of percentage sizes,
        // assign each element a size allowing for a gutter between each
        // pair. The number of gutters is ids.length - 1, and the total gutter
        // size is gutterSize * (ids.length - 1). Before calculating
        // each size, subtract the total gutter size for the parent size.

        parent = document.getElementById(ids[0]).parentNode;

    if (!options.sizes) {
        var percent = 100 / ids.length;

        options.sizes = [];

        for (var i = 0; i < ids.length; i++) {
            options.sizes.push(percent);
        };
    }

    if (!Array.isArray(options.minSize)) {
        var minSizes = [];

        for (var i = 0; i < ids.length; i++) {
            minSizes.push(options.minSize);
        };

        options.minSize = minSizes;
    }

    for (var i = 0; i < ids.length; i++) {
        var el = document.getElementById(ids[i]),
            isFirst = (i == 1),
            isLast = (i == ids.length - 1),
            gutterSize = options.gutterSize;

        // IE9 and above
        if (!isIE8) {
            if (i > 0) {
                var pair = {
                        a: document.getElementById(ids[i - 1]),
                        b: el,
                        aMin: options.minSize[i - 1],
                        bMin: options.minSize[i],
                        dragging: false,
                        parent: parent,
                        isFirst: isFirst,
                        isLast: isLast,
                        direction: options.direction
                    },
                    gutter = document.createElement('div');

                if (options.direction == 'horizontal') {
                    gutter.className = 'gutter gutter-horizontal';
                    gutter.style.width = options.gutterSize + 'px';
                } else {
                    gutter.className = 'gutter gutter-vertical';
                    gutter.style.height = options.gutterSize + 'px';
                }

                gutter.addEventListener('mousedown', startDragging.bind(pair));

                parent.addEventListener('mouseup', stopDragging.bind(pair));
                parent.addEventListener('mousemove', drag.bind(pair));
                parent.addEventListener('mouseleave', stopDragging.bind(pair));

                parent.insertBefore(gutter, el);

                pair.gutter = gutter;
            }

            if (i == 0 || i == ids.length - 1) {
                gutterSize = options.gutterSize / 2;
            }

            var size = calc + '(' + options.sizes[i] + '% - ' + gutterSize + 'px)';

        // IE8 and below
        } else {
            var size = options.sizes[i] + '%';
        }

        if (options.direction == 'horizontal') {
            el.style.width = size;
        } else if (options.direction == 'vertical') {
            el.style.height = size;
        }
    }
};

if (typeof exports !== 'undefined') {
    if (typeof module !== 'undefined' && module.exports) {
        exports = module.exports = Split;
    }
    exports.Split = Split;
} else {
    global.Split = Split;
}

}).call(this);
<commit_msg>remove old comment<commit_after>
'use strict';

(function() {

var global = this;

// Array.isArray Polyfill
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray

if (!Array.isArray) {
  Array.isArray = function(arg) {
    return Object.prototype.toString.call(arg) === '[object Array]';
  };
}

// Check if browser is IE8 or lower

var isIE8 = (function () {
    return (global.attachEvent && !global.addEventListener);
})();

// Get supported calc() prefix

var calc = (function () {
    var prefixes = ["", "-webkit-", "-moz-", "-o-"], el

    for (var i = 0; i < prefixes.length; i++) {
        el = document.createElement('div');
        el.style.cssText = "width:" + prefixes[i] + "calc(9px)";

        if (el.style.length) {
            return prefixes[i] + "calc"
        }
    }
})();

var Split = function (ids, options) {
    // Set defaults

    options = typeof options !== 'undefined' ?  options : {};

    if (!options.gutterSize) options.gutterSize = 10;
    if (!options.minSize) options.minSize = 100;
    if (!options.snapOffset) options.snapOffset = 30;
    if (!options.direction) options.direction = 'horizontal';

    // Event listeners for drag events, bound to a pair object.
    // Save the pair's position and size when dragging starts.
    // Prevent selection on start and re-enable it when done.

    var startDragging = function (e) {
            e.preventDefault();

            this.dragging = true;

            // The first and last pairs have 1.5x gutter (1 in the middle and 1/2 on the side).
            // All other pairs have 2x gutter (1 in the middle and 1/2 on each side).
            // Special case for pairs that are first and last (only 1 pair).

            if (this.isFirst && this.isLast) {
                gutterSize = options.gutterSize;
            } else if (this.isFirst || this.isLast) {
                gutterSize = options.gutterSize * 1.5;
            } else {
                gutterSize = options.gutterSize * 2;
            }

            // Calculate the pairs size, and percentage of the parent size

            if (this.direction == 'horizontal') {
                this.size = this.a.getBoundingClientRect().width + this.b.getBoundingClientRect().width + gutterSize;
                this.percentage = Math.min(this.size / this.parent.clientWidth * 100, 100);
                this.start = this.a.getBoundingClientRect().left;
            } else if (this.direction == 'vertical') {
                this.size = this.a.getBoundingClientRect().height + this.b.getBoundingClientRect().height + gutterSize;
                this.percentage = Math.min(this.size / this.parent.clientHeight * 100, 100);
                this.start = this.a.getBoundingClientRect().top;
            }

            this.a.addEventListener('selectstart', preventSelection);
            this.a.addEventListener('dragstart', preventSelection);
            this.b.addEventListener('selectstart', preventSelection);
            this.b.addEventListener('dragstart', preventSelection);

            this.a.style.userSelect = 'none';
            this.a.style.webkitUserSelect = 'none';
            this.a.style.MozUserSelect = 'none';

            this.b.style.userSelect = 'none';
            this.b.style.webkitUserSelect = 'none';
            this.b.style.MozUserSelect = 'none';

            if (options.onDragStart) {
                options.onDragStart();
            }
        },

        stopDragging = function () {
            this.dragging = false;

            this.a.removeEventListener('selectstart', preventSelection);
            this.a.removeEventListener('dragstart', preventSelection);
            this.b.removeEventListener('selectstart', preventSelection);
            this.b.removeEventListener('dragstart', preventSelection);

            this.a.style.userSelect = '';
            this.a.style.webkitUserSelect = '';
            this.a.style.MozUserSelect = '';

            this.b.style.userSelect = '';
            this.b.style.webkitUserSelect = '';
            this.b.style.MozUserSelect = '';

            if (options.onDragEnd) {
                options.onDragEnd();
            }
        },

        drag = function (e) {
            if (!this.dragging) return;

            // Get the relative position of the event from the first side of the
            // pair.

            if (this.direction == 'horizontal') {
                var offset = e.clientX - this.start;
            } else if (this.direction == 'vertical') {
                var offset = e.clientY - this.start;
            }

            // If within snapOffset of min or max, set offset to min or max

            if (offset <=  this.aMin + options.snapOffset) {
                offset = this.aMin;
            } else if (offset >= this.size - this.bMin - options.snapOffset) {
                offset = this.size - this.bMin;
            }

            // For first and last pairs, first and last gutter width is half.

            var aGutterSize = options.gutterSize;
            var bGutterSize = options.gutterSize;

            if (this.isFirst) {
                aGutterSize = options.gutterSize / 2;
            }

            if (this.isLast) {
                bGutterSize = options.gutterSize / 2;
            }

            // A size is the same as offset. B size is total size - A size.
            // Both sizes are calculated from the initial parent percentage.

            var aSize = calc + '(' + (offset / this.size * this.percentage) + '% - ' + aGutterSize + 'px)';
            var bSize = calc + '(' + (this.percentage - (offset / this.size * this.percentage)) + '% - ' + bGutterSize + 'px)';

            if (this.direction == 'horizontal') {
                this.a.style.width = aSize;
                this.b.style.width = bSize;
            } else if (this.direction == 'vertical') {
                this.a.style.height = aSize;
                this.b.style.height = bSize;
            }

            if (options.onDrag) {
                options.onDrag();
            }
        },

        preventSelection = function () { return false; },

        parent = document.getElementById(ids[0]).parentNode;

    if (!options.sizes) {
        var percent = 100 / ids.length;

        options.sizes = [];

        for (var i = 0; i < ids.length; i++) {
            options.sizes.push(percent);
        };
    }

    if (!Array.isArray(options.minSize)) {
        var minSizes = [];

        for (var i = 0; i < ids.length; i++) {
            minSizes.push(options.minSize);
        };

        options.minSize = minSizes;
    }

    for (var i = 0; i < ids.length; i++) {
        var el = document.getElementById(ids[i]),
            isFirst = (i == 1),
            isLast = (i == ids.length - 1),
            gutterSize = options.gutterSize;

        // IE9 and above
        if (!isIE8) {
            if (i > 0) {
                var pair = {
                        a: document.getElementById(ids[i - 1]),
                        b: el,
                        aMin: options.minSize[i - 1],
                        bMin: options.minSize[i],
                        dragging: false,
                        parent: parent,
                        isFirst: isFirst,
                        isLast: isLast,
                        direction: options.direction
                    },
                    gutter = document.createElement('div');

                if (options.direction == 'horizontal') {
                    gutter.className = 'gutter gutter-horizontal';
                    gutter.style.width = options.gutterSize + 'px';
                } else {
                    gutter.className = 'gutter gutter-vertical';
                    gutter.style.height = options.gutterSize + 'px';
                }

                gutter.addEventListener('mousedown', startDragging.bind(pair));

                parent.addEventListener('mouseup', stopDragging.bind(pair));
                parent.addEventListener('mousemove', drag.bind(pair));
                parent.addEventListener('mouseleave', stopDragging.bind(pair));

                parent.insertBefore(gutter, el);

                pair.gutter = gutter;
            }

            if (i == 0 || i == ids.length - 1) {
                gutterSize = options.gutterSize / 2;
            }

            var size = calc + '(' + options.sizes[i] + '% - ' + gutterSize + 'px)';

        // IE8 and below
        } else {
            var size = options.sizes[i] + '%';
        }

        if (options.direction == 'horizontal') {
            el.style.width = size;
        } else if (options.direction == 'vertical') {
            el.style.height = size;
        }
    }
};

if (typeof exports !== 'undefined') {
    if (typeof module !== 'undefined' && module.exports) {
        exports = module.exports = Split;
    }
    exports.Split = Split;
} else {
    global.Split = Split;
}

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


<commit_before>/// Copyright by Erik Weitnauer, 2012.

/// The point class represents a point or vector in R^2. The interpretations as
/// vector or point are used interchangingly below.

/// Construct point with coordinates x, y. Default is 0, 0.
Point = function(x, y) {
  this.x = x || 0;
  this.y = y || 0;
}

/// Return distance to other point.
Point.prototype.dist = function(other) {
  var dx = this.x-other.x, dy = this.y-other.y;
  return Math.sqrt(dx*dx + dy*dy);
}

/// Return quadratic distance to other point.
Point.prototype.dist2 = function(other) {
  var dx = this.x-other.x, dy = this.y-other.y;
  return dx*dx + dy*dy;
}

/// Return distance to (0, 0).
Point.prototype.length = function() {
  return Math.sqrt(this.x*this.x+this.y*this.y);
}

/// Return quadratic distance to (0, 0).
Point.prototype.length2 = function() {
  return this.x*this.x+this.y*this.y;
}

/// Return new point that is the sum of this and other point.
Point.prototype.add = function(other) {
  return new Point(this.x+other.x, this.y+other.y);
}

/// Add the other point to this and return this.
Point.prototype.Add = function(other) {
  this.x += other.x; this.y += other.y;
  return this;
}

/// Return new point that is the other point subtracted from this.
Point.prototype.sub = function(other) {
  return new Point(this.x-other.x, this.y-other.y);
}

/// Subtract other point from this and return this.
Point.prototype.Sub = function(other) {
  this.x -= other.x; this.y -= other.y;
  return this;
}

/// Return the scalar product of this and the passed vector.
Point.prototype.mul = function(other) {
  return this.x*other.x+this.y*other.y;
}

/// Return last component of cross product of this and other vector.
Point.prototype.cross = function(other) {
  return this.x*other.y-this.y*other.x;
}

/// Return true if x and y components of this do not differ more than eps from other.
Point.prototype.equals = function(other, eps) {
  return (Math.abs(this.x-other.x) < eps) && (Math.abs(this.y-other.y) < eps);
}

/// Returns a new vector with same direction as this but length of 1. Not defined
/// for vector (0, 0).
Point.prototype.normalize = function() {
  var l = 1/this.length();
  return new Point(this.x*l, this.y*l);
}

/// Scales this vector to a length of 1 and returns this.
Point.prototype.Normalize = function() {
  var l = 1/this.length();
  this.x *= l; this.y *= l;
  return this;
}

/// Returns a scaled version of this vector as a new vector.
Point.prototype.scale = function(s) {
  return new Point(this.x*s, this.y*s);
}

/// Scales this vector and returns this.
Point.prototype.Scale = function(s) {
  this.x *= s; this.y *= s;
  return this;
}

/// Returns "(x, y)".
Point.prototype.toString = function() {
  return "(" + this.x + "," + this.y + ")";
}

/// Returns a copy of this point.
Point.prototype.copy = function() {
  return new Point(this.x, this.y);
}

/// To points closer than EPS are considered equal in several algorithms below.
Point.EPS = 1e-6;

/// Returns the closest point on a line segment to a given point.
Point.get_closest_point_on_segment = function(A, B, P) {
  var AB = B.sub(A), ABn = AB.normalize();
  var k = ABn.mul(P.sub(A));
  if (k<0) return A;
  if (k>AB.length()) return B;
  return A.add(ABn.scale(k));
}

/// Calculates the intersection point between a ray and a line segment.
/** The ray is passed as origin and direction vector, the line segment
 * as its two end points A and B. If an intersection is found, the method
 * writes it to the passed intersection point and returns true. If no
 * intersection is found, the method returns false.
 *
 * If there is more than one intersection point (might happen when ray and line
 * segment are parallel), the first intersection point is returned.
 *
 * In order not to miss an intersection with the ray and one of the end points
 * of AB, the method will regard very close misses (which are closer than
 * margin) as collisions, too.
 *
 * Params:
 *   R: start of ray (Point)
 *   v: direction vector of ray (Point)
 *   A, B: start and end point of line segment (Point)
 *   intersection: intersection point is written into this (Point)!!
 *   margin: if ray misses the segment by 'margin' or less, it is regarded as hit (default is Point.EPS)
 */
Point.intersect_ray_with_segment = function(R, v, A, B, intersection, margin) {
  // if there is an intersection, it is at A+l*(B-A)
  // where l = (A-R) x v / (v x (B-A))
  // with a x b ... cross product (applied to 2D) between a and b
  if (typeof(intersection) == 'undefined') var intersection = new Point();
  if (typeof(margin) == 'undefined') var margin = Point.EPS;
  // so we start with calculating the divisor
  var AB = B.sub(A);
  var divisor = v.cross(AB);
  if (Math.abs(divisor) > Point.EPS) {
    // divisor is not zero -- no parallel lines!
    // now calculate l
    var l = (A.sub(R)).cross(v) / divisor;
    // check if we have an intersection
    if (l < -margin || l-1. > margin) return false;
    var hit = A.add(AB.scale(l));
    intersection.x = hit.x; intersection.y = hit.y;
  } else {
    // devisor is zero so first check check for A!=B and v!=0
    if (v.length2() < Point.EPS || AB.length2() < Point.EPS)
      return false;
    // okay, A!=B and v!=0 so this means the lines are parallel
    // we project R onto AB to get its relative position k: R' = A + k*(B-A)
    var k = R.sub(A).mul(AB) / AB.mul(AB);
    // now first check, whether v and AB are colinear
    if (A.add(AB.scale(k)).dist(R) > Point.EPS) return false;
    // they are colinear so there might be an intersection, but it depends where
    // R is relative to AB
    if (k < -margin) { intersection.x = A.x; intersection.y = A.y}
    else if (k - 1. > margin) { intersection.x = B.x; intersection.y = B.y}
    else {intersection.x = R.x; intersection.y = R.y}
  }
  // direction check
  if (intersection.sub(R).mul(v) >= 0.) return true;
  else return false;
}

/// This line is for the automated tests with node.js
if (typeof(exports) != 'undefined') { exports.Point = Point }
<commit_msg>added set() method to point class<commit_after>/// Copyright by Erik Weitnauer, 2012.

/// The point class represents a point or vector in R^2. The interpretations as
/// vector or point are used interchangingly below.

/// Construct point with coordinates x, y. Default is 0, 0.
Point = function(x, y) {
  this.x = x || 0;
  this.y = y || 0;
}

/// Sets x and y to passed values and returns this.
Point.prototype.set = function(x, y) {
  this.x = x; this.y = y;
  return this;
}

/// Return distance to other point.
Point.prototype.dist = function(other) {
  var dx = this.x-other.x, dy = this.y-other.y;
  return Math.sqrt(dx*dx + dy*dy);
}

/// Return quadratic distance to other point.
Point.prototype.dist2 = function(other) {
  var dx = this.x-other.x, dy = this.y-other.y;
  return dx*dx + dy*dy;
}

/// Return distance to (0, 0).
Point.prototype.length = function() {
  return Math.sqrt(this.x*this.x+this.y*this.y);
}

/// Return quadratic distance to (0, 0).
Point.prototype.length2 = function() {
  return this.x*this.x+this.y*this.y;
}

/// Return new point that is the sum of this and other point.
Point.prototype.add = function(other) {
  return new Point(this.x+other.x, this.y+other.y);
}

/// Add the other point to this and return this.
Point.prototype.Add = function(other) {
  this.x += other.x; this.y += other.y;
  return this;
}

/// Return new point that is the other point subtracted from this.
Point.prototype.sub = function(other) {
  return new Point(this.x-other.x, this.y-other.y);
}

/// Subtract other point from this and return this.
Point.prototype.Sub = function(other) {
  this.x -= other.x; this.y -= other.y;
  return this;
}

/// Return the scalar product of this and the passed vector.
Point.prototype.mul = function(other) {
  return this.x*other.x+this.y*other.y;
}

/// Return last component of cross product of this and other vector.
Point.prototype.cross = function(other) {
  return this.x*other.y-this.y*other.x;
}

/// Return true if x and y components of this do not differ more than eps from other.
Point.prototype.equals = function(other, eps) {
  return (Math.abs(this.x-other.x) < eps) && (Math.abs(this.y-other.y) < eps);
}

/// Returns a new vector with same direction as this but length of 1. Not defined
/// for vector (0, 0).
Point.prototype.normalize = function() {
  var l = 1/this.length();
  return new Point(this.x*l, this.y*l);
}

/// Scales this vector to a length of 1 and returns this.
Point.prototype.Normalize = function() {
  var l = 1/this.length();
  this.x *= l; this.y *= l;
  return this;
}

/// Returns a scaled version of this vector as a new vector.
Point.prototype.scale = function(s) {
  return new Point(this.x*s, this.y*s);
}

/// Scales this vector and returns this.
Point.prototype.Scale = function(s) {
  this.x *= s; this.y *= s;
  return this;
}

/// Returns "(x, y)".
Point.prototype.toString = function() {
  return "(" + this.x + "," + this.y + ")";
}

/// Returns a copy of this point.
Point.prototype.copy = function() {
  return new Point(this.x, this.y);
}

/// To points closer than EPS are considered equal in several algorithms below.
Point.EPS = 1e-6;

/// Returns the closest point on a line segment to a given point.
Point.get_closest_point_on_segment = function(A, B, P) {
  var AB = B.sub(A), ABn = AB.normalize();
  var k = ABn.mul(P.sub(A));
  if (k<0) return A;
  if (k>AB.length()) return B;
  return A.add(ABn.scale(k));
}

/// Calculates the intersection point between a ray and a line segment.
/** The ray is passed as origin and direction vector, the line segment
 * as its two end points A and B. If an intersection is found, the method
 * writes it to the passed intersection point and returns true. If no
 * intersection is found, the method returns false.
 *
 * If there is more than one intersection point (might happen when ray and line
 * segment are parallel), the first intersection point is returned.
 *
 * In order not to miss an intersection with the ray and one of the end points
 * of AB, the method will regard very close misses (which are closer than
 * margin) as collisions, too.
 *
 * Params:
 *   R: start of ray (Point)
 *   v: direction vector of ray (Point)
 *   A, B: start and end point of line segment (Point)
 *   intersection: intersection point is written into this (Point)!!
 *   margin: if ray misses the segment by 'margin' or less, it is regarded as hit (default is Point.EPS)
 */
Point.intersect_ray_with_segment = function(R, v, A, B, intersection, margin) {
  // if there is an intersection, it is at A+l*(B-A)
  // where l = (A-R) x v / (v x (B-A))
  // with a x b ... cross product (applied to 2D) between a and b
  if (typeof(intersection) == 'undefined') var intersection = new Point();
  if (typeof(margin) == 'undefined') var margin = Point.EPS;
  // so we start with calculating the divisor
  var AB = B.sub(A);
  var divisor = v.cross(AB);
  if (Math.abs(divisor) > Point.EPS) {
    // divisor is not zero -- no parallel lines!
    // now calculate l
    var l = (A.sub(R)).cross(v) / divisor;
    // check if we have an intersection
    if (l < -margin || l-1. > margin) return false;
    var hit = A.add(AB.scale(l));
    intersection.x = hit.x; intersection.y = hit.y;
  } else {
    // devisor is zero so first check check for A!=B and v!=0
    if (v.length2() < Point.EPS || AB.length2() < Point.EPS)
      return false;
    // okay, A!=B and v!=0 so this means the lines are parallel
    // we project R onto AB to get its relative position k: R' = A + k*(B-A)
    var k = R.sub(A).mul(AB) / AB.mul(AB);
    // now first check, whether v and AB are colinear
    if (A.add(AB.scale(k)).dist(R) > Point.EPS) return false;
    // they are colinear so there might be an intersection, but it depends where
    // R is relative to AB
    if (k < -margin) { intersection.x = A.x; intersection.y = A.y}
    else if (k - 1. > margin) { intersection.x = B.x; intersection.y = B.y}
    else {intersection.x = R.x; intersection.y = R.y}
  }
  // direction check
  if (intersection.sub(R).mul(v) >= 0.) return true;
  else return false;
}

/// This line is for the automated tests with node.js
if (typeof(exports) != 'undefined') { exports.Point = Point }
<|endoftext|>


<commit_before>// Copyright (c) 2014 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

// Application start script. This launches Mongo, then delegates to main.js.
// meteor-spk will automatically include this in your package; you don't need
// to worry about it.
//
// The original version of meteor-spk used Niscu[1], a fork of Mongo that adjusts
// some compiled-in constants to optimize for a small disk footprint. As of Mongo 3.0,
// we no longer need Niscu, because the WiredTiger storage engine can be configured
// to suit our needs. This script performs the migration from Niscu to Mongo 3.0,
// if necessary.
//
// [1] https://github.com/kentonv/mongo/tree/niscu

var child_process = require("child_process");
var fs = require("fs");
var Promise = require("es6-promise").Promise;
var MongoClient = require('mongodb').MongoClient;

var appPort = "4000";
var mongoPort = "4001";
var niscuPort = "4002";
if (process.argv.length > 3) {
  // You can pass in a port number for the app to listen on:
  // `node start.js -p <port number>`
  if (process.argv[2] !== "-p") {
    throw new Error("-p is the only option currently supported");
  }
  var appPortNum = parseInt(process.argv[3]);
  if (isNaN(appPortNum)) {
    throw new Error("could not parse a port number from: " + process.argv[2]);
  }
  appPort = appPortNum.toString();
  mongoPort = (appPortNum + 1).toString();
  niscuPort = (appPortNum + 2).toString();
}

var dbPath = "/var/wiredTigerDb"

function runChildProcess(child, name, continuation) {
// Runs the process until it exits successfully. Then calls the continuation.
  child.on("error", function (err) {
    console.error("error in " + name + ": "  + err.stack);
    process.exit(1);
  });

  child.on("exit", function (code, signal) {
    if (signal) {
      console.error(name + " failed with signal: " + signal);
      process.exit(1);
    }
    if (code !== 0) {
      console.error(name + " exited with error code: " + code);
      process.exit(1);
    }
    continuation();
  });
}

function startMongo(continuation) {
  console.log("** Starting Mongo...");
  var db = child_process.spawn("/bin/mongod",
                               [ "--fork", "--port", mongoPort, "--dbpath", dbPath,
                                 "--noauth", "--bind_ip", "127.0.0.1", "--nohttpinterface",
                                 "--storageEngine", "wiredTiger",
                                 "--wiredTigerEngineConfigString",
                                 "log=(prealloc=false,file_max=200KB)",
                                 "--wiredTigerCacheSizeGB", "1",
                                 "--logpath", dbPath + "/mongo.log" ],
                               { stdio: "inherit" });

  runChildProcess(db, "Mongo", continuation);
}

function runApp() {
  console.log("** Starting Meteor...");
  process.env.MONGO_URL="mongodb://127.0.0.1:" + mongoPort + "/meteor";
  process.env.ROOT_URL="http://127.0.0.1:" + appPort;
  process.env.PORT=appPort;
  require("./main.js");
}

var migrationDumpPath = "/var/migrationMongoDump";
// Back when we used mongodump for migration, this was a directory containing the dumped data.
// Now it's just an empty file, the existence of which implies that a migration is in progress.

if (fs.existsSync(dbPath) && !fs.existsSync(migrationDumpPath)) {
  startMongo(runApp);
} else {
  // The old database was in /var.
  if (!fs.existsSync("/var/journal")) {
    // No migration required.
    fs.mkdirSync(dbPath);
    startMongo(runApp);
  } else {
    console.log("Starting migration to WiredTiger storage engine...");

    if (fs.existsSync(migrationDumpPath)) {
      console.log("It looks like a previous attempt to migrate failed. Cleaning it up...");
      var now = (new Date()).getTime();
      if (fs.existsSync(dbPath)) {
        fs.rename(dbPath, "/var/failedMigration" + now);
      }
      fs.rename(migrationDumpPath, "/var/failedMigrationDump" + now);
      // Can't just call unlinkSync() because it might be a directory with mongodump contents.
    }
    fs.writeFileSync(migrationDumpPath, "");

    console.log("launching niscud");
    var oldDbProcess = child_process.spawn("/bin/niscud", [ "--fork",
                                                            "--port", niscuPort,
                                                            "--dbpath", "/var",
                                                            "--noauth", "--bind_ip", "127.0.0.1",
                                                            "--nohttpinterface", "--noprealloc",
                                                            "--logpath", "/var/mongo.log" ], {
                                                              stdio: "inherit"
                                                            });
    fs.mkdirSync(dbPath);
    runChildProcess(oldDbProcess, "nisucd", function () {
      startMongo(function () {
        var niscuUrl = "mongodb://127.0.0.1:" + niscuPort + "/meteor";
        var mongoUrl = "mongodb://127.0.0.1:" + mongoPort + "/meteor";
        MongoClient.connect(niscuUrl, {}).then(function(oldDb) {
          return MongoClient.connect(mongoUrl, {}).then(function(newDb) {
            return {oldDb: oldDb, newDb: newDb};
          });
        }).then(function (dbs) {
          return dbs.oldDb.collections().then(function (oldCollections) {
            var collectionPromises = [];
            oldCollections.forEach(function(oldCollection) {
              console.log("collection: " + oldCollection.collectionName);
              if (oldCollection.collectionName.slice(0, 7)  === "system.") {
                // Ignore system.indexes and other special collections.
                // If the app uses createIndex() or ensureIndex() sensibly, the indexes
                // should be regenerated on the next start of the app.
                return;
              }
              var promise = dbs.newDb.createCollection(oldCollection.collectionName)
                  .then(function (newCollection) {
                function insertionLoop(cursor) {
                  return cursor.hasNext().then(function (hasNext) {
                    if (hasNext) {
                      return cursor.next().then(function (doc) {
                        return newCollection.insertOne(doc).then(function () {
                          return insertionLoop(cursor);
                        });
                      });
                    }
                  });
                }
                return insertionLoop(oldCollection.find());
              });
              collectionPromises.push(promise);
            });
            return Promise.all(collectionPromises).then(function () {
              dbs.oldDb.admin().command({shutdown: 1});
              // We don't wait for success of this command because the server kills itself
              // before it sends a confirmation.

              fs.unlinkSync(migrationDumpPath);
              // Success!

              runApp();
            });
          });
        }).catch(function(e) {
          console.log("error: " + e);
        });
      });
    });
  }
}

<commit_msg>rename() -> renameSync()<commit_after>// Copyright (c) 2014 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

// Application start script. This launches Mongo, then delegates to main.js.
// meteor-spk will automatically include this in your package; you don't need
// to worry about it.
//
// The original version of meteor-spk used Niscu[1], a fork of Mongo that adjusts
// some compiled-in constants to optimize for a small disk footprint. As of Mongo 3.0,
// we no longer need Niscu, because the WiredTiger storage engine can be configured
// to suit our needs. This script performs the migration from Niscu to Mongo 3.0,
// if necessary.
//
// [1] https://github.com/kentonv/mongo/tree/niscu

var child_process = require("child_process");
var fs = require("fs");
var Promise = require("es6-promise").Promise;
var MongoClient = require('mongodb').MongoClient;

var appPort = "4000";
var mongoPort = "4001";
var niscuPort = "4002";
if (process.argv.length > 3) {
  // You can pass in a port number for the app to listen on:
  // `node start.js -p <port number>`
  if (process.argv[2] !== "-p") {
    throw new Error("-p is the only option currently supported");
  }
  var appPortNum = parseInt(process.argv[3]);
  if (isNaN(appPortNum)) {
    throw new Error("could not parse a port number from: " + process.argv[2]);
  }
  appPort = appPortNum.toString();
  mongoPort = (appPortNum + 1).toString();
  niscuPort = (appPortNum + 2).toString();
}

var dbPath = "/var/wiredTigerDb"

function runChildProcess(child, name, continuation) {
// Runs the process until it exits successfully. Then calls the continuation.
  child.on("error", function (err) {
    console.error("error in " + name + ": "  + err.stack);
    process.exit(1);
  });

  child.on("exit", function (code, signal) {
    if (signal) {
      console.error(name + " failed with signal: " + signal);
      process.exit(1);
    }
    if (code !== 0) {
      console.error(name + " exited with error code: " + code);
      process.exit(1);
    }
    continuation();
  });
}

function startMongo(continuation) {
  console.log("** Starting Mongo...");
  var db = child_process.spawn("/bin/mongod",
                               [ "--fork", "--port", mongoPort, "--dbpath", dbPath,
                                 "--noauth", "--bind_ip", "127.0.0.1", "--nohttpinterface",
                                 "--storageEngine", "wiredTiger",
                                 "--wiredTigerEngineConfigString",
                                 "log=(prealloc=false,file_max=200KB)",
                                 "--wiredTigerCacheSizeGB", "1",
                                 "--logpath", dbPath + "/mongo.log" ],
                               { stdio: "inherit" });

  runChildProcess(db, "Mongo", continuation);
}

function runApp() {
  console.log("** Starting Meteor...");
  process.env.MONGO_URL="mongodb://127.0.0.1:" + mongoPort + "/meteor";
  process.env.ROOT_URL="http://127.0.0.1:" + appPort;
  process.env.PORT=appPort;
  require("./main.js");
}

var migrationDumpPath = "/var/migrationMongoDump";
// Back when we used mongodump for migration, this was a directory containing the dumped data.
// Now it's just an empty file, the existence of which implies that a migration is in progress.

if (fs.existsSync(dbPath) && !fs.existsSync(migrationDumpPath)) {
  startMongo(runApp);
} else {
  // The old database was in /var.
  if (!fs.existsSync("/var/journal")) {
    // No migration required.
    fs.mkdirSync(dbPath);
    startMongo(runApp);
  } else {
    console.log("Starting migration to WiredTiger storage engine...");

    if (fs.existsSync(migrationDumpPath)) {
      console.log("It looks like a previous attempt to migrate failed. Cleaning it up...");
      var now = (new Date()).getTime();
      if (fs.existsSync(dbPath)) {
        fs.renameSync(dbPath, "/var/failedMigration" + now);
      }
      fs.renameSync(migrationDumpPath, "/var/failedMigrationDump" + now);
      // Can't just call unlinkSync() because it might be a directory with mongodump contents.
    }
    fs.writeFileSync(migrationDumpPath, "");

    console.log("launching niscud");
    var oldDbProcess = child_process.spawn("/bin/niscud", [ "--fork",
                                                            "--port", niscuPort,
                                                            "--dbpath", "/var",
                                                            "--noauth", "--bind_ip", "127.0.0.1",
                                                            "--nohttpinterface", "--noprealloc",
                                                            "--logpath", "/var/mongo.log" ], {
                                                              stdio: "inherit"
                                                            });
    fs.mkdirSync(dbPath);
    runChildProcess(oldDbProcess, "nisucd", function () {
      startMongo(function () {
        var niscuUrl = "mongodb://127.0.0.1:" + niscuPort + "/meteor";
        var mongoUrl = "mongodb://127.0.0.1:" + mongoPort + "/meteor";
        MongoClient.connect(niscuUrl, {}).then(function(oldDb) {
          return MongoClient.connect(mongoUrl, {}).then(function(newDb) {
            return {oldDb: oldDb, newDb: newDb};
          });
        }).then(function (dbs) {
          return dbs.oldDb.collections().then(function (oldCollections) {
            var collectionPromises = [];
            oldCollections.forEach(function(oldCollection) {
              console.log("collection: " + oldCollection.collectionName);
              if (oldCollection.collectionName.slice(0, 7)  === "system.") {
                // Ignore system.indexes and other special collections.
                // If the app uses createIndex() or ensureIndex() sensibly, the indexes
                // should be regenerated on the next start of the app.
                return;
              }
              var promise = dbs.newDb.createCollection(oldCollection.collectionName)
                  .then(function (newCollection) {
                function insertionLoop(cursor) {
                  return cursor.hasNext().then(function (hasNext) {
                    if (hasNext) {
                      return cursor.next().then(function (doc) {
                        return newCollection.insertOne(doc).then(function () {
                          return insertionLoop(cursor);
                        });
                      });
                    }
                  });
                }
                return insertionLoop(oldCollection.find());
              });
              collectionPromises.push(promise);
            });
            return Promise.all(collectionPromises).then(function () {
              dbs.oldDb.admin().command({shutdown: 1});
              // We don't wait for success of this command because the server kills itself
              // before it sends a confirmation.

              fs.unlinkSync(migrationDumpPath);
              // Success!

              runApp();
            });
          });
        }).catch(function(e) {
          console.log("error: " + e);
        });
      });
    });
  }
}

<|endoftext|>


<commit_before>
'use strict';

// 入口文件
var startFn = require('./index');
// 默认配置
var setting = require('./config').mock;
//获取端口

module.exports = function(d,p,cb){
	var dir = d || process.cwd(),
		port = p || setting.port;
	startFn(dir,port,cb)
}
<commit_msg>fix a bug<commit_after>
'use strict';

// 入口文件
var startFn = require('./index');
// 默认配置
var setting = require('./config').mock;

module.exports = function(d,p,cb){
	var dir = d || process.cwd(),
		port = p || setting.port;
	startFn(dir,port,cb)
}
<|endoftext|>


<commit_before>var registry = require('./registry');
var manifest = require('./manifest');

var exports = {};

// Recently updated packages //////////////////////////////////////////////////

function UpdatedPackage(name, version, previous) {
	this.name = name;
	this.version = version;
	this.previous = previous;
}

var recentlyUpdatedPackages = [];

registry.on('change', function (change) {
	console.log(change);
	var versions = Object.keys(change.doc.versions);

	if (versions.length < 2) {
		return;
	}

	var pkg = new UpdatedPackage(change.doc.name, versions[versions.length - 1], versions[versions.length - 2]);

	for (var i = 0; i < recentlyUpdatedPackages.length; i++) {
		if (recentlyUpdatedPackages[i].name === pkg.name) {
			recentlyUpdatedPackages.splice(i, 1);
			break;
		}
	}

	recentlyUpdatedPackages.unshift(pkg);

	if(recentlyUpdatedPackages.length > 10) {
		recentlyUpdatedPackages.pop();
	}
});

exports.getRecentlyUpdatedPackages = function() {
	return recentlyUpdatedPackages.slice();
};

// Recently retrieved manifests ///////////////////////////////////////////////

function RetrievedManifest(manifest, user, repo) {
	this.manifest = manifest;
	this.user = user;
	this.repo = repo;
}

var recentlyRetrievedManifests = [];

manifest.on('retrieve', function(manifest, user, repo) {

	var inList = false;

	for (var i = 0; i < recentlyRetrievedManifests.length; ++i) {

		if (recentlyRetrievedManifests[i].user === user && recentlyRetrievedManifests[i].repo === repo) {
			recentlyRetrievedManifests.splice(i, 1);
			inList = true;
			break;
		}
	}

	recentlyRetrievedManifests.unshift(new RetrievedManifest(manifest, user, repo));

	if (!inList && recentlyRetrievedManifests.length > 10) {
		recentlyRetrievedManifests.pop();
	}
});

exports.getRecentlyRetrievedManifests = function() {
	return recentlyRetrievedManifests.slice();
};

// Recently updated manifests /////////////////////////////////////////////////

function UpdatedManifest(diffs, manifest, user, repo) {
	this.diffs = diffs;
	this.manifest = manifest;
	this.user = user;
	this.repo = repo;
}

var recentlyUpdatedManifests = [];

manifest.on('dependenciesChange', function(diffs, manifest, user, repo) {

	recentlyUpdatedManifests.unshift(new UpdatedManifest(diffs, manifest, user, repo));

	if (recentlyUpdatedManifests.length > 10) {
		recentlyUpdatedManifests.pop();
	}
});

exports.getRecentlyUpdatedManifests = function() {
	return recentlyUpdatedManifests.slice();
};

// Dependency counts //////////////////////////////////////////////////////////

var dependencyCounts = {};

// When manifest first retrieved, +1 all the dependencies
manifest.on('retrieve', function(manifest) {

	var depNames = Object.keys(manifest.dependencies || {});

	depNames.forEach(function(depName) {
		dependencyCounts[depName] = dependencyCounts[depName] || 0;
		dependencyCounts[depName]++;
	});
});

// If the manifest dependencies change, +1 or -1 if dependencies are added or removed
manifest.on('dependenciesChange', function(diffs) {

	diffs.forEach(function(diff) {

		// Dependency added
		if (!diff.previous) {
			dependencyCounts[diff.name] = dependencyCounts[diff.name] || 0;
			dependencyCounts[diff.name]++;
		}

		// Dependency removed
		if (diff.version === null) {
			dependencyCounts[diff.name]--;
		}
	});
});

exports.getDependencyCounts = function() {
	return JSON.parse(JSON.stringify(dependencyCounts));
};

module.exports = exports;
<commit_msg>Guard against doc with no versions field due to registry delete<commit_after>var registry = require('./registry');
var manifest = require('./manifest');

var exports = {};

// Recently updated packages //////////////////////////////////////////////////

function UpdatedPackage(name, version, previous) {
	this.name = name;
	this.version = version;
	this.previous = previous;
}

var recentlyUpdatedPackages = [];

registry.on('change', function (change) {
	if (!change.doc.versions) {
		return;
	}

	var versions = Object.keys(change.doc.versions);

	if (versions.length < 2) {
		return;
	}

	var pkg = new UpdatedPackage(change.doc.name, versions[versions.length - 1], versions[versions.length - 2]);

	for (var i = 0; i < recentlyUpdatedPackages.length; i++) {
		if (recentlyUpdatedPackages[i].name === pkg.name) {
			recentlyUpdatedPackages.splice(i, 1);
			break;
		}
	}

	recentlyUpdatedPackages.unshift(pkg);

	if(recentlyUpdatedPackages.length > 10) {
		recentlyUpdatedPackages.pop();
	}
});

exports.getRecentlyUpdatedPackages = function() {
	return recentlyUpdatedPackages.slice();
};

// Recently retrieved manifests ///////////////////////////////////////////////

function RetrievedManifest(manifest, user, repo) {
	this.manifest = manifest;
	this.user = user;
	this.repo = repo;
}

var recentlyRetrievedManifests = [];

manifest.on('retrieve', function(manifest, user, repo) {

	var inList = false;

	for (var i = 0; i < recentlyRetrievedManifests.length; ++i) {

		if (recentlyRetrievedManifests[i].user === user && recentlyRetrievedManifests[i].repo === repo) {
			recentlyRetrievedManifests.splice(i, 1);
			inList = true;
			break;
		}
	}

	recentlyRetrievedManifests.unshift(new RetrievedManifest(manifest, user, repo));

	if (!inList && recentlyRetrievedManifests.length > 10) {
		recentlyRetrievedManifests.pop();
	}
});

exports.getRecentlyRetrievedManifests = function() {
	return recentlyRetrievedManifests.slice();
};

// Recently updated manifests /////////////////////////////////////////////////

function UpdatedManifest(diffs, manifest, user, repo) {
	this.diffs = diffs;
	this.manifest = manifest;
	this.user = user;
	this.repo = repo;
}

var recentlyUpdatedManifests = [];

manifest.on('dependenciesChange', function(diffs, manifest, user, repo) {

	recentlyUpdatedManifests.unshift(new UpdatedManifest(diffs, manifest, user, repo));

	if (recentlyUpdatedManifests.length > 10) {
		recentlyUpdatedManifests.pop();
	}
});

exports.getRecentlyUpdatedManifests = function() {
	return recentlyUpdatedManifests.slice();
};

// Dependency counts //////////////////////////////////////////////////////////

var dependencyCounts = {};

// When manifest first retrieved, +1 all the dependencies
manifest.on('retrieve', function(manifest) {

	var depNames = Object.keys(manifest.dependencies || {});

	depNames.forEach(function(depName) {
		dependencyCounts[depName] = dependencyCounts[depName] || 0;
		dependencyCounts[depName]++;
	});
});

// If the manifest dependencies change, +1 or -1 if dependencies are added or removed
manifest.on('dependenciesChange', function(diffs) {

	diffs.forEach(function(diff) {

		// Dependency added
		if (!diff.previous) {
			dependencyCounts[diff.name] = dependencyCounts[diff.name] || 0;
			dependencyCounts[diff.name]++;
		}

		// Dependency removed
		if (diff.version === null) {
			dependencyCounts[diff.name]--;
		}
	});
});

exports.getDependencyCounts = function() {
	return JSON.parse(JSON.stringify(dependencyCounts));
};

module.exports = exports;
<|endoftext|>


<commit_before>var dgram  = require('dgram')
  , sys    = require('sys')
  , net    = require('net')
  , config = require('./config')

var counters = {};
var timers = {};
var debugInt, flushInt, server, mgmtServer;
var startup_time = Math.round(new Date().getTime() / 1000);

var stats = {
  graphite: {
    last_flush: startup_time,
    last_exception: startup_time
  },
  messages: {
    last_msg_seen: startup_time,
    bad_lines_seen: 0,
  }
};

config.configFile(process.argv[2], function (config, oldConfig) {
  if (! config.debug && debugInt) {
    clearInterval(debugInt);
    debugInt = false;
  }

  if (config.debug) {
    if (debugInt !== undefined) { clearInterval(debugInt); }
    debugInt = setInterval(function () {
      sys.log("Counters:\n" + sys.inspect(counters) + "\nTimers:\n" + sys.inspect(timers));
    }, config.debugInterval || 10000);
  }

  if (server === undefined) {
    server = dgram.createSocket('udp4', function (msg, rinfo) {
      if (config.dumpMessages) { sys.log(msg.toString()); }
      var bits = msg.toString().split(':');
      var key = bits.shift()
                    .replace(/\s+/g, '_')
                    .replace(/\//g, '-')
                    .replace(/[^a-zA-Z_\-0-9\.]/g, '');

      if (bits.length == 0) {
        bits.push("1");
      }

      for (var i = 0; i < bits.length; i++) {
        var sampleRate = 1;
        var fields = bits[i].split("|");
        if (fields[1] === undefined) {
            sys.log('Bad line: ' + fields);
            stats['messages']['bad_lines_seen']++;
            continue;
        }
        if (fields[1].trim() == "ms") {
          if (! timers[key]) {
            timers[key] = [];
          }
          timers[key].push(Number(fields[0] || 0));
        } else {
          if (fields[2] && fields[2].match(/^@([\d\.]+)/)) {
            sampleRate = Number(fields[2].match(/^@([\d\.]+)/)[1]);
          }
          if (! counters[key]) {
            counters[key] = 0;
          }
          counters[key] += Number(fields[0] || 1) * (1 / sampleRate);
        }
      }

      stats['messages']['last_msg_seen'] = Math.round(new Date().getTime() / 1000);
    });

    mgmtServer = net.createServer(function(stream) {
      stream.setEncoding('ascii');

      stream.on('data', function(data) {
        var cmd = data.trim();

        switch(cmd) {
          case "help":
            stream.write("Commands: stats, counters, timers, quit\n\n");
            break;

          case "stats":
            var now    = Math.round(new Date().getTime() / 1000);
            var uptime = now - startup_time;

            stream.write("uptime: " + uptime + "\n");

            for (group in stats) {
              for (metric in stats[group]) {
                var val;

                if (metric.match("^last_")) {
                  val = now - stats[group][metric];
                }
                else {
                  val = stats[group][metric];
                }

                stream.write(group + "." + metric + ": " + val + "\n");
              }
            }
            stream.write("END\n\n");
            break;

          case "counters":
            stream.write(sys.inspect(counters) + "\n");
            stream.write("END\n\n");
            break;

          case "timers":
            stream.write(sys.inspect(timers) + "\n");
            stream.write("END\n\n");
            break;

          case "quit":
            stream.end();
            break;

          default:
            stream.write("ERROR\n");
            break;
        }

      });
    });

    server.bind(config.port || 8125);
    mgmtServer.listen(config.mgmt_port || 8126);

    var flushInterval = Number(config.flushInterval || 10000);

    flushInt = setInterval(function () {
      var statString = '';
      var ts = Math.round(new Date().getTime() / 1000);
      var numStats = 0;
      var key;

      for (key in counters) {
        var value = counters[key] / (flushInterval / 1000);
        var message = 'stats.' + key + ' ' + value + ' ' + ts + "\n";
        message += 'stats_counts.' + key + ' ' + counters[key] + ' ' + ts + "\n";
        statString += message;
        counters[key] = 0;

        numStats += 1;
      }

      for (key in timers) {
        if (timers[key].length > 0) {
          var pctThreshold = config.percentThreshold || 90;
          var values = timers[key].sort(function (a,b) { return a-b; });
          var count = values.length;
          var min = values[0];
          var max = values[count - 1];

          var mean = min;
          var maxAtThreshold = max;

          if (count > 1) {
            var thresholdIndex = Math.round(((100 - pctThreshold) / 100) * count);
            var numInThreshold = count - thresholdIndex;
            values = values.slice(0, numInThreshold);
            maxAtThreshold = values[numInThreshold - 1];

            // average the remaining timings
            var sum = 0;
            for (var i = 0; i < numInThreshold; i++) {
              sum += values[i];
            }

            mean = sum / numInThreshold;
          }

          timers[key] = [];

          var message = "";
          message += 'stats.timers.' + key + '.mean ' + mean + ' ' + ts + "\n";
          message += 'stats.timers.' + key + '.upper ' + max + ' ' + ts + "\n";
          message += 'stats.timers.' + key + '.upper_' + pctThreshold + ' ' + maxAtThreshold + ' ' + ts + "\n";
          message += 'stats.timers.' + key + '.lower ' + min + ' ' + ts + "\n";
          message += 'stats.timers.' + key + '.count ' + count + ' ' + ts + "\n";
          statString += message;

          numStats += 1;
        }
      }

      statString += 'statsd.numStats ' + numStats + ' ' + ts + "\n";

      try {
        var graphite = net.createConnection(config.graphitePort, config.graphiteHost);
        graphite.addListener('error', function(connectionException){
          if (config.debug) {
            sys.log(connectionException);
          }
        });
        graphite.on('connect', function() {
          this.write(statString);
          this.end();
          stats['graphite']['last_flush'] = Math.round(new Date().getTime() / 1000);
        });
      } catch(e){
        if (config.debug) {
          sys.log(e);
        }
        stats['graphite']['last_exception'] = Math.round(new Date().getTime() / 1000);
      }

    }, flushInterval);
  }

});

<commit_msg>Allow binding to a specific interface<commit_after>var dgram  = require('dgram')
  , sys    = require('sys')
  , net    = require('net')
  , config = require('./config')

var counters = {};
var timers = {};
var debugInt, flushInt, server, mgmtServer;
var startup_time = Math.round(new Date().getTime() / 1000);

var stats = {
  graphite: {
    last_flush: startup_time,
    last_exception: startup_time
  },
  messages: {
    last_msg_seen: startup_time,
    bad_lines_seen: 0,
  }
};

config.configFile(process.argv[2], function (config, oldConfig) {
  if (! config.debug && debugInt) {
    clearInterval(debugInt);
    debugInt = false;
  }

  if (config.debug) {
    if (debugInt !== undefined) { clearInterval(debugInt); }
    debugInt = setInterval(function () {
      sys.log("Counters:\n" + sys.inspect(counters) + "\nTimers:\n" + sys.inspect(timers));
    }, config.debugInterval || 10000);
  }

  if (server === undefined) {
    server = dgram.createSocket('udp4', function (msg, rinfo) {
      if (config.dumpMessages) { sys.log(msg.toString()); }
      var bits = msg.toString().split(':');
      var key = bits.shift()
                    .replace(/\s+/g, '_')
                    .replace(/\//g, '-')
                    .replace(/[^a-zA-Z_\-0-9\.]/g, '');

      if (bits.length == 0) {
        bits.push("1");
      }

      for (var i = 0; i < bits.length; i++) {
        var sampleRate = 1;
        var fields = bits[i].split("|");
        if (fields[1] === undefined) {
            sys.log('Bad line: ' + fields);
            stats['messages']['bad_lines_seen']++;
            continue;
        }
        if (fields[1].trim() == "ms") {
          if (! timers[key]) {
            timers[key] = [];
          }
          timers[key].push(Number(fields[0] || 0));
        } else {
          if (fields[2] && fields[2].match(/^@([\d\.]+)/)) {
            sampleRate = Number(fields[2].match(/^@([\d\.]+)/)[1]);
          }
          if (! counters[key]) {
            counters[key] = 0;
          }
          counters[key] += Number(fields[0] || 1) * (1 / sampleRate);
        }
      }

      stats['messages']['last_msg_seen'] = Math.round(new Date().getTime() / 1000);
    });

    mgmtServer = net.createServer(function(stream) {
      stream.setEncoding('ascii');

      stream.on('data', function(data) {
        var cmd = data.trim();

        switch(cmd) {
          case "help":
            stream.write("Commands: stats, counters, timers, quit\n\n");
            break;

          case "stats":
            var now    = Math.round(new Date().getTime() / 1000);
            var uptime = now - startup_time;

            stream.write("uptime: " + uptime + "\n");

            for (group in stats) {
              for (metric in stats[group]) {
                var val;

                if (metric.match("^last_")) {
                  val = now - stats[group][metric];
                }
                else {
                  val = stats[group][metric];
                }

                stream.write(group + "." + metric + ": " + val + "\n");
              }
            }
            stream.write("END\n\n");
            break;

          case "counters":
            stream.write(sys.inspect(counters) + "\n");
            stream.write("END\n\n");
            break;

          case "timers":
            stream.write(sys.inspect(timers) + "\n");
            stream.write("END\n\n");
            break;

          case "quit":
            stream.end();
            break;

          default:
            stream.write("ERROR\n");
            break;
        }

      });
    });

    server.bind(config.port || 8125, config.address || undefined);
    mgmtServer.listen(config.mgmt_port || 8126, config.mgmt_address || undefined);

    var flushInterval = Number(config.flushInterval || 10000);

    flushInt = setInterval(function () {
      var statString = '';
      var ts = Math.round(new Date().getTime() / 1000);
      var numStats = 0;
      var key;

      for (key in counters) {
        var value = counters[key] / (flushInterval / 1000);
        var message = 'stats.' + key + ' ' + value + ' ' + ts + "\n";
        message += 'stats_counts.' + key + ' ' + counters[key] + ' ' + ts + "\n";
        statString += message;
        counters[key] = 0;

        numStats += 1;
      }

      for (key in timers) {
        if (timers[key].length > 0) {
          var pctThreshold = config.percentThreshold || 90;
          var values = timers[key].sort(function (a,b) { return a-b; });
          var count = values.length;
          var min = values[0];
          var max = values[count - 1];

          var mean = min;
          var maxAtThreshold = max;

          if (count > 1) {
            var thresholdIndex = Math.round(((100 - pctThreshold) / 100) * count);
            var numInThreshold = count - thresholdIndex;
            values = values.slice(0, numInThreshold);
            maxAtThreshold = values[numInThreshold - 1];

            // average the remaining timings
            var sum = 0;
            for (var i = 0; i < numInThreshold; i++) {
              sum += values[i];
            }

            mean = sum / numInThreshold;
          }

          timers[key] = [];

          var message = "";
          message += 'stats.timers.' + key + '.mean ' + mean + ' ' + ts + "\n";
          message += 'stats.timers.' + key + '.upper ' + max + ' ' + ts + "\n";
          message += 'stats.timers.' + key + '.upper_' + pctThreshold + ' ' + maxAtThreshold + ' ' + ts + "\n";
          message += 'stats.timers.' + key + '.lower ' + min + ' ' + ts + "\n";
          message += 'stats.timers.' + key + '.count ' + count + ' ' + ts + "\n";
          statString += message;

          numStats += 1;
        }
      }

      statString += 'statsd.numStats ' + numStats + ' ' + ts + "\n";

      try {
        var graphite = net.createConnection(config.graphitePort, config.graphiteHost);
        graphite.addListener('error', function(connectionException){
          if (config.debug) {
            sys.log(connectionException);
          }
        });
        graphite.on('connect', function() {
          this.write(statString);
          this.end();
          stats['graphite']['last_flush'] = Math.round(new Date().getTime() / 1000);
        });
      } catch(e){
        if (config.debug) {
          sys.log(e);
        }
        stats['graphite']['last_exception'] = Math.round(new Date().getTime() / 1000);
      }

    }, flushInterval);
  }

});

<|endoftext|>


<commit_before>function TimeStore(n){
  this.n = n || 1;
  this.size = 512;
  this.data = new Int32Array(this.size * this.n);
  this.deltas = new Uint32Array(this.size);
  this.idx = 0;
  this.count = 0;
  this.last = this.now();
}

TimeStore.prototype.now = function(){
  return Date.now();
}

TimeStore.prototype.add = function(){

  this.idx = (this.idx || this.size) - 1;

  for (var i = 0; i < this.n; i++)
    this.data[(this.idx*this.n) + i] = arguments[i];

  this.count ++;

  // store the timestamp diff of this event
  var now = this.now();
  var delta = now - this.last;
  this.deltas[this.idx] = delta;
  this.last = now;
}

TimeStore.prototype.each = function(milliseconds, fn){
  milliseconds -= (this.now() - this.last);

  var args = new Array(this.n);

  var offset = 0, offsetMax = Math.min(this.count, this.size);
  while(offset < offsetMax){
    if(milliseconds<0) break;

    var i = (this.idx + offset) % this.size;

    for (var j = 0; j < this.n; j++) {
      args[j] = this.data[(i*this.n) + j];
    }

    fn.apply(null, args);

    milliseconds -= this.deltas[i];
    offset++;
  }
}

TimeStore.prototype.extent = function(milliseconds){
  milliseconds -= (this.now() - this.last);

  var min = new Array(this.n), max = new Array(this.n), i, v;
  var offset = 0, offsetMax = Math.min(this.count, this.size);
  while(offset < offsetMax){
    if(milliseconds<0) break;

    i = (this.idx + offset) % this.size;

    for (var j = 0; j < this.n; j++) {
      v = this.data[(i*this.n) + j];
      min[j] = offset ? Math.min(min[j], v) : v;
      max[j] = offset ? Math.max(max[j], v) : v;
    }

    milliseconds -= this.deltas[i];
    offset++;
  }

  return min.map(function(min, i) {
    return [min, max[i]];
  });
}

TimeStore.prototype.distance = function(milliseconds){
  return Math.sqrt(
    this.extent(milliseconds)
      .reduce(function(memo, e) {
        return Math.pow(e[1] - e[0], 2) + memo;
      },0)
  );
}

function Store(size, n) {
  this.size = size || 128;
  this.n = n || 1;

  this.i = 0;
  this.data = new Uint8Array(size * n);

  // count of items stored
  this.count = 0;
}

Store.prototype.add = function(i) {
  if (!Array.isArray(i)) {i = [i];};

  // overflow possible
  this.data.set(i, this.i * this.n);

  // decrement round (makes scanning easier)
  this.i = this.i ? this.i - 1 : this.size - 1;

  this.count ++;
};

Store.prototype.take = function(c, fn) {
  c = Math.min(c, this.size, this.count);

  for (var i = 1; i < c + 1; i++) {
    var idx = ((this.i + i) % this.size) * this.n;
    var arr = this.data.subarray(idx, idx + this.n);
    fn.apply(this, [].slice.call(arr,0));
  }
};

Store.prototype.extent = function(c) {

  c = Math.min(c, this.size, this.count);

  var _n = this.n;
  var min = new Array(_n), max = new Array(_n);

  for (var i = 1; i < c + 1; i++) {
    var idx = ((this.i + i) % this.size) * this.n;
    for (var j = 0; j < _n; j++) {
      if (i == 1) {
        min[j] = max[j] = this.data[idx + j];
      } else {
        min[j] = Math.min(min[j], this.data[idx + j]);
        max[j] = Math.max(max[j], this.data[idx + j]);
      }
    }
  }

  return min.map(function(min, i) {
    return [min, max[i]];
  });
};

Store.prototype.distance = function(i) {

  return Math.sqrt(
    this.extent(i)
      .reduce(function(memo, e) {
        return Math.pow(e[1] - e[0], 2) + memo;
      },0)
  );

};
<commit_msg>jscs whatever<commit_after>function TimeStore(n) {
  this.n = n || 1;
  this.size = 512;
  this.data = new Int32Array(this.size * this.n);
  this.deltas = new Uint32Array(this.size);
  this.idx = 0;
  this.count = 0;
  this.last = this.now();
}

TimeStore.prototype.now = function() {
  return Date.now();
};

TimeStore.prototype.add = function() {

  this.idx = (this.idx || this.size) - 1;

  for (var i = 0; i < this.n; i++)
    this.data[(this.idx * this.n) + i] = arguments[i];

  this.count++;

  // store the timestamp diff of this event
  var now = this.now();
  var delta = now - this.last;
  this.deltas[this.idx] = delta;
  this.last = now;
};

TimeStore.prototype.each = function(milliseconds, fn) {
  milliseconds -= (this.now() - this.last);

  var args = new Array(this.n);

  var offset = 0, offsetMax = Math.min(this.count, this.size);
  while (offset < offsetMax) {
    if (milliseconds < 0) break;

    var i = (this.idx + offset) % this.size;

    for (var j = 0; j < this.n; j++) {
      args[j] = this.data[(i * this.n) + j];
    }

    fn.apply(null, args);

    milliseconds -= this.deltas[i];
    offset++;
  }
};

TimeStore.prototype.extent = function(milliseconds) {
  milliseconds -= (this.now() - this.last);

  var min = new Array(this.n), max = new Array(this.n), i, v;
  var offset = 0, offsetMax = Math.min(this.count, this.size);
  while (offset < offsetMax) {
    if (milliseconds < 0) break;

    i = (this.idx + offset) % this.size;

    for (var j = 0; j < this.n; j++) {
      v = this.data[(i * this.n) + j];
      min[j] = offset ? Math.min(min[j], v) : v;
      max[j] = offset ? Math.max(max[j], v) : v;
    }

    milliseconds -= this.deltas[i];
    offset++;
  }

  return min.map(function(min, i) {
    return [min, max[i]];
  });
};

TimeStore.prototype.distance = function(milliseconds) {
  return Math.sqrt(
    this.extent(milliseconds)
      .reduce(function(memo, e) {
        return Math.pow(e[1] - e[0], 2) + memo;
      },0)
  );
};

function Store(size, n) {
  this.size = size || 128;
  this.n = n || 1;

  this.i = 0;
  this.data = new Uint8Array(size * n);

  // count of items stored
  this.count = 0;
}

Store.prototype.add = function(i) {
  if (!Array.isArray(i)) {i = [i];}

  // overflow possible
  this.data.set(i, this.i * this.n);

  // decrement round (makes scanning easier)
  this.i = this.i ? this.i - 1 : this.size - 1;

  this.count ++;
};

Store.prototype.take = function(c, fn) {
  c = Math.min(c, this.size, this.count);

  for (var i = 1; i < c + 1; i++) {
    var idx = ((this.i + i) % this.size) * this.n;
    var arr = this.data.subarray(idx, idx + this.n);
    fn.apply(this, [].slice.call(arr,0));
  }
};

Store.prototype.extent = function(c) {

  c = Math.min(c, this.size, this.count);

  var _n = this.n;
  var min = new Array(_n), max = new Array(_n);

  for (var i = 1; i < c + 1; i++) {
    var idx = ((this.i + i) % this.size) * this.n;
    for (var j = 0; j < _n; j++) {
      if (i == 1) {
        min[j] = max[j] = this.data[idx + j];
      } else {
        min[j] = Math.min(min[j], this.data[idx + j]);
        max[j] = Math.max(max[j], this.data[idx + j]);
      }
    }
  }

  return min.map(function(min, i) {
    return [min, max[i]];
  });
};

Store.prototype.distance = function(i) {

  return Math.sqrt(
    this.extent(i)
      .reduce(function(memo, e) {
        return Math.pow(e[1] - e[0], 2) + memo;
      },0)
  );

};
<|endoftext|>