<commit_before>function SideMenulView() {
	const that = this;

	this.user = undefined;

	var cachedEnvironments;

	function isUserSubscribedOnServer(server) {
		return server.subscribers != undefined && server.subscribers.includes(that.user);
	}

	/*
		Note, that "opened" class affects not the server_selection_button itself but .resources_list
	*/
	function showServerSelection(serverResourcesNode) {
		if(!serverResourcesNode.classList.contains("opened"))
			serverResourcesNode.classList.add("opened");

		removeClassFromOthers(getAllResourcesLists(), serverResourcesNode, "opened");
		removeClassFromOthers(getAllResourceSelectionButtonHolders(), undefined, "selected_resource");
	}

	/*
		Note, that selected_resource class affects not the resource_selection_button itself, but the parent div-node
	*/
	function showResourceSelection(resourceNodeHolder) {
		if(!resourceNodeHolder.classList.contains("selected_resource"))
			resourceNodeHolder.classList.add("selected_resource");

		removeClassFromOthers(getAllResourceSelectionButtonHolders(), resourceNodeHolder, "selected_resource");
	}

	function removeClassFromOthers(allNodes, node, aClass) {
		for(var i = 0; i < allNodes.length; i++)
			if(allNodes[i] != node)
				allNodes[i].classList.remove(aClass);
	}

	function getAllResourcesLists() {
		return document.querySelectorAll(".resources_list");
	}

	function getAllResourceSelectionButtonHolders() {
		//since there is no parent selector in css we will do this manualy

		var buttons = document.querySelectorAll(".resource_selection_button");

		var holders = new Array(buttons.length);
		for(var i = 0; i < buttons.length; i++)
			holders[i] = buttons[i].parentNode;

		return holders;
	}

	function rebuildView(environments) {
		for(var i = 0; i<environments.length; i++)
			rebuildEnvironmentView(environments[i]);

		that.environments = environments;
	}

	function rebuildEnvironmentView(environment) {
		var servers = environment.servers;
		for(var i = 0; i < servers.length; i++)
			rebuildServerAndEnvironmentNode(environment, servers[i]);
	}

	function rebuildServerAndEnvironmentNode(environment, server) {
		var node = findPresentListNodeForEnvironmentAndServer(environment, server);
		if(node) {
			//TODO
		} else {
			node = createNewListNodeForEnvironmentAndServer(environment, server);
			var serverList = document.querySelectorAll("#sidemenu .servers_list:nth-child(1)")[0];
			serverList.appendChild(node);
		}
	}

	function buildEnverironmentServerListNodeName(environment, server) {
		return environment.name + " " + server.name;
	}

	function findPresentListNodeForEnvironmentAndServer(environment, server) {
		var elems = document.querySelectorAll("#environments_list ul li");

		for(var i = 0; i<elems.length; i++) {
			var button = elems[i].querySelector("div div:nth-child(1)");
			if(button.innerHTML== buildEnverironmentServerListNodeName(environment, server))
				return button;
		}

		return undefined;
	}

	function createNewListNodeForEnvironmentAndServer(environment, server) {
		var resourcesList = createNewResourceNodesList(environment, server);

		var selectionButton = document.createElement("a");
		selectionButton.href = "#";
		selectionButton.classList.add("server_selection_button");
		selectionButton.innerHTML= buildEnverironmentServerListNodeName(environment, server);
		selectionButton.onclick = function() {
			showServerSelection(resourcesList);
			that.serverSelectionHandler(environment, server);
		};

		var innerDiv = document.createElement("div");
		if(isUserSubscribedOnServer(server))
			innerDiv.classList.add("subscribed");
		innerDiv.appendChild(selectionButton);

		var outerDiv = document.createElement("div");
		outerDiv.appendChild(innerDiv);
		outerDiv.appendChild(resourcesList);

		var listElem = document.createElement("li");
		listElem.appendChild(outerDiv);

		return listElem;
	}

	function createNewResourceNodesList(environment, server) { var list = document.createElement("ul");
		list.classList.add("resources_list");

		var resources = server.resources;
		for(var i = 0; i<resources.length; i++)
			list.appendChild(createNewResourceNode(environment, server, resources[i]));

		return list;
	}

	function getAvatarUrl(user) {
		return "https://robohash.org/teamnotifier_" + user;
	}

	function createNewResourceNode(environment, server, resource) {
		var innerDiv = document.createElement("div");
		var resourceSelectionButton = document.createElement("a");

		innerDiv.appendChild(resourceSelectionButton);

		resourceSelectionButton.href = "#";
		resourceSelectionButton.innerHTML= resource.name;
		resourceSelectionButton.classList.add("resource_selection_button");
		resourceSelectionButton.onclick = function() {
			showResourceSelection(innerDiv);
			that.resourceSelectionHandler(environment, server, resource);
		};

		var outerDiv = document.createElement("div");
		outerDiv.appendChild(innerDiv);
		if(resource.occupationInfo) {
			var avatar = createNewAvatar(resource.occupationInfo.userName);
			outerDiv.appendChild(avatar);
		}

		var listItem = document.createElement("li");
		listItem.appendChild(outerDiv);

		return listItem;
	}

	function createNewAvatar(user) {
		var innerDiv = document.createElement("div");
		innerDiv.style.backgroundImage = "url('" + getAvatarUrl(user) + "')";

		var outerDiv = document.createElement("div");
		outerDiv.classList.add("avatar");
		outerDiv.appendChild(innerDiv);

		return outerDiv;
	}

	SideMenulView.prototype.setEnvironments = function(env) {
		rebuildView(env);
	}
}

SideMenulView.prototype.serverSelectionHandler = function(environment, server) {
	throw new Error("not binded");
}

SideMenulView.prototype.resourceSelectionHandler = function(environment, server, resource) {
	throw new Error("not binded");
}
<commit_msg>fu firefox<commit_after>function SideMenulView() {
	const that = this;

	this.user = undefined;

	var cachedEnvironments;

	function isUserSubscribedOnServer(server) {
		return server.subscribers != undefined && server.subscribers.length != 0 && server.subscribers.includes(that.user);
	}

	/*
		Note, that "opened" class affects not the server_selection_button itself but .resources_list
	*/
	function showServerSelection(serverResourcesNode) {
		if(!serverResourcesNode.classList.contains("opened"))
			serverResourcesNode.classList.add("opened");

		removeClassFromOthers(getAllResourcesLists(), serverResourcesNode, "opened");
		removeClassFromOthers(getAllResourceSelectionButtonHolders(), undefined, "selected_resource");
	}

	/*
		Note, that selected_resource class affects not the resource_selection_button itself, but the parent div-node
	*/
	function showResourceSelection(resourceNodeHolder) {
		if(!resourceNodeHolder.classList.contains("selected_resource"))
			resourceNodeHolder.classList.add("selected_resource");

		removeClassFromOthers(getAllResourceSelectionButtonHolders(), resourceNodeHolder, "selected_resource");
	}

	function removeClassFromOthers(allNodes, node, aClass) {
		for(var i = 0; i < allNodes.length; i++)
			if(allNodes[i] != node)
				allNodes[i].classList.remove(aClass);
	}

	function getAllResourcesLists() {
		return document.querySelectorAll(".resources_list");
	}

	function getAllResourceSelectionButtonHolders() {
		//since there is no parent selector in css we will do this manualy

		var buttons = document.querySelectorAll(".resource_selection_button");

		var holders = new Array(buttons.length);
		for(var i = 0; i < buttons.length; i++)
			holders[i] = buttons[i].parentNode;

		return holders;
	}

	function rebuildView(environments) {
		for(var i = 0; i<environments.length; i++)
			rebuildEnvironmentView(environments[i]);

		that.environments = environments;
	}

	function rebuildEnvironmentView(environment) {
		var servers = environment.servers;
		for(var i = 0; i < servers.length; i++)
			rebuildServerAndEnvironmentNode(environment, servers[i]);
	}

	function rebuildServerAndEnvironmentNode(environment, server) {
		var node = findPresentListNodeForEnvironmentAndServer(environment, server);
		if(node) {
			//TODO
		} else {
			node = createNewListNodeForEnvironmentAndServer(environment, server);
			var serverList = document.querySelectorAll("#sidemenu .servers_list:nth-child(1)")[0];
			serverList.appendChild(node);
		}
	}

	function buildEnverironmentServerListNodeName(environment, server) {
		return environment.name + " " + server.name;
	}

	function findPresentListNodeForEnvironmentAndServer(environment, server) {
		var elems = document.querySelectorAll("#environments_list ul li");

		for(var i = 0; i<elems.length; i++) {
			var button = elems[i].querySelector("div div:nth-child(1)");
			if(button.innerHTML== buildEnverironmentServerListNodeName(environment, server))
				return button;
		}

		return undefined;
	}

	function createNewListNodeForEnvironmentAndServer(environment, server) {
		var resourcesList = createNewResourceNodesList(environment, server);

		var selectionButton = document.createElement("a");
		selectionButton.href = "#";
		selectionButton.classList.add("server_selection_button");
		selectionButton.innerHTML= buildEnverironmentServerListNodeName(environment, server);
		selectionButton.onclick = function() {
			showServerSelection(resourcesList);
			that.serverSelectionHandler(environment, server);
		};

		var innerDiv = document.createElement("div");
		if(isUserSubscribedOnServer(server))
			innerDiv.classList.add("subscribed");
		innerDiv.appendChild(selectionButton);

		var outerDiv = document.createElement("div");
		outerDiv.appendChild(innerDiv);
		outerDiv.appendChild(resourcesList);

		var listElem = document.createElement("li");
		listElem.appendChild(outerDiv);

		return listElem;
	}

	function createNewResourceNodesList(environment, server) { var list = document.createElement("ul");
		list.classList.add("resources_list");

		var resources = server.resources;
		for(var i = 0; i<resources.length; i++)
			list.appendChild(createNewResourceNode(environment, server, resources[i]));

		return list;
	}

	function getAvatarUrl(user) {
		return "https://robohash.org/teamnotifier_" + user;
	}

	function createNewResourceNode(environment, server, resource) {
		var innerDiv = document.createElement("div");
		var resourceSelectionButton = document.createElement("a");

		innerDiv.appendChild(resourceSelectionButton);

		resourceSelectionButton.href = "#";
		resourceSelectionButton.innerHTML= resource.name;
		resourceSelectionButton.classList.add("resource_selection_button");
		resourceSelectionButton.onclick = function() {
			showResourceSelection(innerDiv);
			that.resourceSelectionHandler(environment, server, resource);
		};

		var outerDiv = document.createElement("div");
		outerDiv.appendChild(innerDiv);
		if(resource.occupationInfo) {
			var avatar = createNewAvatar(resource.occupationInfo.userName);
			outerDiv.appendChild(avatar);
		}

		var listItem = document.createElement("li");
		listItem.appendChild(outerDiv);

		return listItem;
	}

	function createNewAvatar(user) {
		var innerDiv = document.createElement("div");
		innerDiv.style.backgroundImage = "url('" + getAvatarUrl(user) + "')";

		var outerDiv = document.createElement("div");
		outerDiv.classList.add("avatar");
		outerDiv.appendChild(innerDiv);

		return outerDiv;
	}

	SideMenulView.prototype.setEnvironments = function(env) {
		rebuildView(env);
	}
}

SideMenulView.prototype.serverSelectionHandler = function(environment, server) {
	throw new Error("not binded");
}

SideMenulView.prototype.resourceSelectionHandler = function(environment, server, resource) {
	throw new Error("not binded");
}
<|endoftext|>


<commit_before>;(function() {
    var queue = []
    var polling = false
    var delay = 1

    function enqueue(f) {
      queue.push(f)
      schedule()
    }

    function schedule() {
      if (!polling) {
        polling = true
        setTimeout(checkQueue, delay)
      }
    }

    function checkQueue() {
      polling = false
      var chunk = Math.max(1, queue.length / 100)
      var left = chunk
      while (left > 0 && queue.length > 0) {
        var first = queue.splice(0,1)[0]
        first()
        left--
      }
      if (queue.length > 0) {
        schedule()
      }
    }

    function repeat(times, f) {
      if (times > 0) {
        f()
        repeat(times - 1, f)
      }
    }
    function delayed(f) {
      return function() {
        enqueue(f)
      }
    }
    function stepper(total, step, f) {
      if (total < 0) step = -step
      function delayedStep(s) {
        return delayed(function() {
            f(s)
        })
      }
      repeat(Math.floor(Math.abs(total / step)), delayedStep(step))
      var remainder = total % step
      if (remainder) {
        delayedStep(remainder)()
      }
    }
  window.Smoothly = {
    step: stepper,
    do: delayed
  }
})()

<commit_msg>improve performance of smoothly.js<commit_after>;(function() {
    var queue = []
    var polling = false
    var delay = 1

    function enqueue(f) {
      queue.push(f)
      schedule()
    }

    function schedule() {
      if (!polling) {
        polling = true
        setTimeout(checkQueue, delay)
      }
    }

    function checkQueue() {
      polling = false
      var chunkSize = Math.min(queue.length, Math.floor(Math.max(1, queue.length / 100)))
      if (chunkSize > 0) {
        var todo = queue.splice(0, chunkSize)
        for (var i = 0; i < chunkSize; i++) {
          todo[i]()
        }
        if (queue.length > 0) {
          schedule()
        }
      }
    }

    function repeat(times, f) {
      if (times > 0) {
        f()
        repeat(times - 1, f)
      }
    }
    function delayed(f) {
      return function() {
        enqueue(f)
      }
    }
    function stepper(total, step, f) {
      if (total < 0) step = -step
      function delayedStep(s) {
        return delayed(function() {
            f(s)
        })
      }
      repeat(Math.floor(Math.abs(total / step)), delayedStep(step))
      var remainder = total % step
      if (remainder) {
        delayedStep(remainder)()
      }
    }
  window.Smoothly = {
    step: stepper,
    do: delayed
  }
})()

<|endoftext|>


<commit_before>/**
 * Bundler, used in builder script to statically
 * include snippets.json into bundle
 */
var res = require('../lib/assets/resources');
var snippets = require('../lib/snippets.json');
res.setVocabulary(snippets, true);
<commit_msg>Fixed default vocabulary loading<commit_after>/**
 * Bundler, used in builder script to statically
 * include snippets.json into bundle
 */
var res = require('../lib/assets/resources');
var snippets = require('../lib/snippets.json');
res.setVocabulary(snippets, 'system');
<|endoftext|>


<commit_before>/**
 * @author Russell Toris - rctoris@wpi.edu
 */

/**
 * A marker client that listens to a given marker topic.
 *
 * Emits the following events:
 *  * 'change' - there was an update or change in the marker
 *
 * @constructor
 * @param options - object with following keys:
 *   * ros - the ROSLIB.Ros connection handle
 *   * topic (optional) - the map topic to listen to
 *   * rootObject (optional) - the root object to add this marker to
 *   * continuous (optional) - if the map should be continuously loaded (e.g., for SLAM)
 */
ROS3D.OccupancyGridClient = function(options) {
  var that = this;
  var options = options || {};
  var ros = options.ros;
  var topic = options.topic || '/map';
  this.tfClient = options.tfClient;
  this.rootObject = options.rootObject || new THREE.Object3D();

  // current grid that is displayed
  this.currentGrid = null;

  // subscribe to the topic
  var rosTopic = new ROSLIB.Topic({
    ros : ros,
    name : topic,
    messageType : 'nav_msgs/OccupancyGrid',
    compression : 'png'
  });
  rosTopic.subscribe(function(message) {
    // check for an old marker
    if (that.currentGrid) {
      that.rootObject.remove(that.currentGrid);
    }

    that.currentGrid = new ROS3D.OccupancyGrid({
      message : message
    });
    that.rootObject.add(that.currentGrid);

    that.emit('change');
  });
};
ROS3D.OccupancyGridClient.prototype.__proto__ = EventEmitter2.prototype;
<commit_msg>continuous flag in OccupancyGridClient fixed<commit_after>/**
 * @author Russell Toris - rctoris@wpi.edu
 */

/**
 * A marker client that listens to a given marker topic.
 *
 * Emits the following events:
 *  * 'change' - there was an update or change in the marker
 *
 * @constructor
 * @param options - object with following keys:
 *   * ros - the ROSLIB.Ros connection handle
 *   * topic (optional) - the map topic to listen to
 *   * rootObject (optional) - the root object to add this marker to
 *   * continuous (optional) - if the map should be continuously loaded (e.g., for SLAM)
 */
ROS3D.OccupancyGridClient = function(options) {
  var that = this;
  var options = options || {};
  var ros = options.ros;
  var topic = options.topic || '/map';
  this.continuous = options.continuous;
  this.rootObject = options.rootObject || new THREE.Object3D();

  // current grid that is displayed
  this.currentGrid = null;

  // subscribe to the topic
  var rosTopic = new ROSLIB.Topic({
    ros : ros,
    name : topic,
    messageType : 'nav_msgs/OccupancyGrid',
    compression : 'png'
  });
  rosTopic.subscribe(function(message) {
    // check for an old marker
    if (that.currentGrid) {
      that.rootObject.remove(that.currentGrid);
    }

    that.currentGrid = new ROS3D.OccupancyGrid({
      message : message
    });
    that.rootObject.add(that.currentGrid);

    that.emit('change');

    // check if we should unsubscribe
    if(!that.continuous) {
      rosTopic.unsubscribe();
    }
  });
};
ROS3D.OccupancyGridClient.prototype.__proto__ = EventEmitter2.prototype;
<|endoftext|>


<commit_before>/* jshint noempty: false */

/**
* @author       Richard Davey <rich@photonstorm.com>
* @copyright    2014 Photon Storm Ltd.
* @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/

/**
* Phaser.RandomDataGenerator constructor.
*
* @class Phaser.RandomDataGenerator
* @classdesc An extremely useful repeatable random data generator. Access it via Phaser.Game.rnd
* Based on Nonsense by Josh Faul https://github.com/jocafa/Nonsense.
* Random number generator from http://baagoe.org/en/wiki/Better_random_numbers_for_javascript
*
* @constructor
* @param {array} seeds
*/
Phaser.RandomDataGenerator = function (seeds) {

    if (typeof seeds === "undefined") { seeds = []; }

    /**
    * @property {number} c - Internal var.
    * @private
    */
    this.c = 1;

    /**
    * @property {number} s0 - Internal var.
    * @private
    */
    this.s0 = 0;

    /**
    * @property {number} s1 - Internal var.
    * @private
    */
    this.s1 = 0;

    /**
    * @property {number} s2 - Internal var.
    * @private
    */
    this.s2 = 0;

    this.sow(seeds);

};

Phaser.RandomDataGenerator.prototype = {

    /**
    * Private random helper.
    *
    * @method Phaser.RandomDataGenerator#rnd
    * @private
    * @return {number}
    */
    rnd: function () {

        var t = 2091639 * this.s0 + this.c * 2.3283064365386963e-10; // 2^-32

        this.c = t | 0;
        this.s0 = this.s1;
        this.s1 = this.s2;
        this.s2 = t - this.c;

        return this.s2;
    },

    /**
    * Reset the seed of the random data generator.
    *
    * @method Phaser.RandomDataGenerator#sow
    * @param {array} seeds
    */
    sow: function (seeds) {

        if (typeof seeds === "undefined") { seeds = []; }

        this.s0 = this.hash(' ');
        this.s1 = this.hash(this.s0);
        this.s2 = this.hash(this.s1);
        this.c = 1;

        var seed;

        for (var i = 0; seed = seeds[i++]; )
        {
            this.s0 -= this.hash(seed);
            this.s0 += ~~(this.s0 < 0);
            this.s1 -= this.hash(seed);
            this.s1 += ~~(this.s1 < 0);
            this.s2 -= this.hash(seed);
            this.s2 += ~~(this.s2 < 0);
        }

    },

    /**
    * Internal method that creates a seed hash.
    *
    * @method Phaser.RandomDataGenerator#hash
    * @private
    * @param {Any} data
    * @return {number} hashed value.
    */
    hash: function (data) {

        var h, i, n;
        n = 0xefc8249d;
        data = data.toString();

        for (i = 0; i < data.length; i++) {
            n += data.charCodeAt(i);
            h = 0.02519603282416938 * n;
            n = h >>> 0;
            h -= n;
            h *= n;
            n = h >>> 0;
            h -= n;
            n += h * 0x100000000;// 2^32
        }

        return (n >>> 0) * 2.3283064365386963e-10;// 2^-32

    },

    /**
    * Returns a random integer between 0 and 2^32.
    *
    * @method Phaser.RandomDataGenerator#integer
    * @return {number} A random integer between 0 and 2^32.
    */
    integer: function() {

        return this.rnd.apply(this) * 0x100000000;// 2^32

    },

    /**
    * Returns a random real number between 0 and 1.
    *
    * @method Phaser.RandomDataGenerator#frac
    * @return {number} A random real number between 0 and 1.
    */
    frac: function() {

        return this.rnd.apply(this) + (this.rnd.apply(this) * 0x200000 | 0) * 1.1102230246251565e-16;   // 2^-53

    },

    /**
    * Returns a random real number between 0 and 2^32.
    *
    * @method Phaser.RandomDataGenerator#real
    * @return {number} A random real number between 0 and 2^32.
    */
    real: function() {

        return this.integer() + this.frac();

    },

    /**
    * Returns a random integer between and including min and max.
    *
    * @method Phaser.RandomDataGenerator#integerInRange
    * @param {number} min - The minimum value in the range.
    * @param {number} max - The maximum value in the range.
    * @return {number} A random number between min and max.
    */
    integerInRange: function (min, max) {

        return Math.floor(this.realInRange(0, max - min + 1)) + min;

    },

    /**
    * Returns a random real number between min and max.
    *
    * @method Phaser.RandomDataGenerator#realInRange
    * @param {number} min - The minimum value in the range.
    * @param {number} max - The maximum value in the range.
    * @return {number} A random number between min and max.
    */
    realInRange: function (min, max) {

        return this.frac() * (max - min) + min;

    },

    /**
    * Returns a random real number between -1 and 1.
    *
    * @method Phaser.RandomDataGenerator#normal
    * @return {number} A random real number between -1 and 1.
    */
    normal: function () {

        return 1 - 2 * this.frac();

    },

    /**
    * Returns a valid RFC4122 version4 ID hex string from https://gist.github.com/1308368
    *
    * @method Phaser.RandomDataGenerator#uuid
    * @return {string} A valid RFC4122 version4 ID hex string
    */
    uuid: function () {

        var a = '';
        var b = '';

        for (b = a = ''; a++ < 36; b +=~a % 5 | a * 3&4 ? (a^15 ? 8^this.frac() * (a^20 ? 16 : 4) : 4).toString(16) : '-')
        {
        }

        return b;

    },

    /**
    * Returns a random member of `array`.
    *
    * @method Phaser.RandomDataGenerator#pick
    * @param {Array} ary - An Array to pick a random member of.
    * @return {any} A random member of the array.
    */
    pick: function (ary) {

        return ary[this.integerInRange(0, ary.length - 1)];

    },

    /**
    * Returns a random member of `array`, favoring the earlier entries.
    *
    * @method Phaser.RandomDataGenerator#weightedPick
    * @param {Array} ary - An Array to pick a random member of.
    * @return {any} A random member of the array.
    */
    weightedPick: function (ary) {

        return ary[~~(Math.pow(this.frac(), 2) * (ary.length - 1))];

    },

    /**
    * Returns a random timestamp between min and max, or between the beginning of 2000 and the end of 2020 if min and max aren't specified.
    *
    * @method Phaser.RandomDataGenerator#timestamp
    * @param {number} min - The minimum value in the range.
    * @param {number} max - The maximum value in the range.
    * @return {number} A random timestamp between min and max.
    */
    timestamp: function (min, max) {

        return this.realInRange(min || 946684800000, max || 1577862000000);

    },

    /**
    * Returns a random angle between -180 and 180.
    *
    * @method Phaser.RandomDataGenerator#angle
    * @return {number} A random number between -180 and 180.
    */
    angle: function() {

        return this.integerInRange(-180, 180);

    }

};

Phaser.RandomDataGenerator.prototype.constructor = Phaser.RandomDataGenerator;
<commit_msg>jshint fix<commit_after>/* jshint noempty: false */

/**
* @author       Richard Davey <rich@photonstorm.com>
* @copyright    2014 Photon Storm Ltd.
* @license      {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/

/**
* Phaser.RandomDataGenerator constructor.
*
* @class Phaser.RandomDataGenerator
* @classdesc An extremely useful repeatable random data generator. Access it via Phaser.Game.rnd
* Based on Nonsense by Josh Faul https://github.com/jocafa/Nonsense.
* Random number generator from http://baagoe.org/en/wiki/Better_random_numbers_for_javascript
*
* @constructor
* @param {array} seeds
*/
Phaser.RandomDataGenerator = function (seeds) {

    if (typeof seeds === "undefined") { seeds = []; }

    /**
    * @property {number} c - Internal var.
    * @private
    */
    this.c = 1;

    /**
    * @property {number} s0 - Internal var.
    * @private
    */
    this.s0 = 0;

    /**
    * @property {number} s1 - Internal var.
    * @private
    */
    this.s1 = 0;

    /**
    * @property {number} s2 - Internal var.
    * @private
    */
    this.s2 = 0;

    this.sow(seeds);

};

Phaser.RandomDataGenerator.prototype = {

    /**
    * Private random helper.
    *
    * @method Phaser.RandomDataGenerator#rnd
    * @private
    * @return {number}
    */
    rnd: function () {

        var t = 2091639 * this.s0 + this.c * 2.3283064365386963e-10; // 2^-32

        this.c = t | 0;
        this.s0 = this.s1;
        this.s1 = this.s2;
        this.s2 = t - this.c;

        return this.s2;
    },

    /**
    * Reset the seed of the random data generator.
    *
    * @method Phaser.RandomDataGenerator#sow
    * @param {array} seeds
    */
    sow: function (seeds) {

        if (typeof seeds === "undefined") { seeds = []; }

        this.s0 = this.hash(' ');
        this.s1 = this.hash(this.s0);
        this.s2 = this.hash(this.s1);
        this.c = 1;

        var seed;

        for (var i = 0; seed = seeds[i++]; )
        {
            this.s0 -= this.hash(seed);
            this.s0 += ~~(this.s0 < 0);
            this.s1 -= this.hash(seed);
            this.s1 += ~~(this.s1 < 0);
            this.s2 -= this.hash(seed);
            this.s2 += ~~(this.s2 < 0);
        }

    },

    /**
    * Internal method that creates a seed hash.
    *
    * @method Phaser.RandomDataGenerator#hash
    * @private
    * @param {Any} data
    * @return {number} hashed value.
    */
    hash: function (data) {

        var h, i, n;
        n = 0xefc8249d;
        data = data.toString();

        for (i = 0; i < data.length; i++) {
            n += data.charCodeAt(i);
            h = 0.02519603282416938 * n;
            n = h >>> 0;
            h -= n;
            h *= n;
            n = h >>> 0;
            h -= n;
            n += h * 0x100000000;// 2^32
        }

        return (n >>> 0) * 2.3283064365386963e-10;// 2^-32

    },

    /**
    * Returns a random integer between 0 and 2^32.
    *
    * @method Phaser.RandomDataGenerator#integer
    * @return {number} A random integer between 0 and 2^32.
    */
    integer: function() {

        return this.rnd.apply(this) * 0x100000000;// 2^32

    },

    /**
    * Returns a random real number between 0 and 1.
    *
    * @method Phaser.RandomDataGenerator#frac
    * @return {number} A random real number between 0 and 1.
    */
    frac: function() {

        return this.rnd.apply(this) + (this.rnd.apply(this) * 0x200000 | 0) * 1.1102230246251565e-16;   // 2^-53

    },

    /**
    * Returns a random real number between 0 and 2^32.
    *
    * @method Phaser.RandomDataGenerator#real
    * @return {number} A random real number between 0 and 2^32.
    */
    real: function() {

        return this.integer() + this.frac();

    },

    /**
    * Returns a random integer between and including min and max.
    *
    * @method Phaser.RandomDataGenerator#integerInRange
    * @param {number} min - The minimum value in the range.
    * @param {number} max - The maximum value in the range.
    * @return {number} A random number between min and max.
    */
    integerInRange: function (min, max) {

        return Math.floor(this.realInRange(0, max - min + 1)) + min;

    },

    /**
    * Returns a random real number between min and max.
    *
    * @method Phaser.RandomDataGenerator#realInRange
    * @param {number} min - The minimum value in the range.
    * @param {number} max - The maximum value in the range.
    * @return {number} A random number between min and max.
    */
    realInRange: function (min, max) {

        return this.frac() * (max - min) + min;

    },

    /**
    * Returns a random real number between -1 and 1.
    *
    * @method Phaser.RandomDataGenerator#normal
    * @return {number} A random real number between -1 and 1.
    */
    normal: function () {

        return 1 - 2 * this.frac();

    },

    /**
    * Returns a valid RFC4122 version4 ID hex string from https://gist.github.com/1308368
    *
    * @method Phaser.RandomDataGenerator#uuid
    * @return {string} A valid RFC4122 version4 ID hex string
    */
    uuid: function () {

        var a = '';
        var b = '';

        for (b = a = ''; a++ < 36; b +=~a % 5 | a * 3&4 ? (a^15 ? 8^this.frac() * (a^20 ? 16 : 4) : 4).toString(16) : '-')
        {
        }

        return b;

    },

    /**
    * Returns a random member of `array`.
    *
    * @method Phaser.RandomDataGenerator#pick
    * @param {Array} ary - An Array to pick a random member of.
    * @return {any} A random member of the array.
    */
    pick: function (ary) {

        return ary[this.integerInRange(0, ary.length - 1)];

    },

    /**
    * Returns a random member of `array`, favoring the earlier entries.
    *
    * @method Phaser.RandomDataGenerator#weightedPick
    * @param {Array} ary - An Array to pick a random member of.
    * @return {any} A random member of the array.
    */
    weightedPick: function (ary) {

        return ary[~~(Math.pow(this.frac(), 2) * (ary.length - 1))];

    },

    /**
    * Returns a random timestamp between min and max, or between the beginning of 2000 and the end of 2020 if min and max aren't specified.
    *
    * @method Phaser.RandomDataGenerator#timestamp
    * @param {number} min - The minimum value in the range.
    * @param {number} max - The maximum value in the range.
    * @return {number} A random timestamp between min and max.
    */
    timestamp: function (min, max) {

        return this.realInRange(min || 946684800000, max || 1577862000000);

    },

    /**
    * Returns a random angle between -180 and 180.
    *
    * @method Phaser.RandomDataGenerator#angle
    * @return {number} A random number between -180 and 180.
    */
    angle: function() {

        return this.integerInRange(-180, 180);

    }

};

Phaser.RandomDataGenerator.prototype.constructor = Phaser.RandomDataGenerator;
<|endoftext|>


<commit_before>var DesktopNotification = Notification;

var Notification = {
    inhibed : false,
    focused : false,
    tab_counter1 : 0,
    tab_counter2 : 0,
    tab_counter1_key : 'chat',
    tab_counter2_key : 'news',
    document_title_init : null,
    document_title : document.title,
    notifs_key : '',
    favicon : null,
    electron : null,

    inhibit : function(sec) {
        Notification.inhibed = true;

        if(sec == null) sec = 5;

        setTimeout(function() {
                Notification.inhibed = false;
            },
            sec*1000);
    },
    refresh : function(keys) {console.log(keys);
        var counters = document.querySelectorAll('.counter');
        for(i = 0; i < counters.length; i++) {
            var n = counters[i];
            if(n.dataset.key != null
            && keys[n.dataset.key] != null) {
                n.innerHTML = keys[n.dataset.key];
            }
        }

        for(var key in keys) {
            var counter = keys[key];
            Notification.setTab(key, counter);
        }

        Notification.displayTab();
    },
    counter : function(key, counter) {
        var counters = document.querySelectorAll('.counter');
        for(i = 0; i < counters.length; i++) {
            var n = counters[i];
            if(n.dataset.key != null
            && n.dataset.key == key) {
                n.innerHTML = counter;
            }
        }

        Notification.setTab(key, counter);
        Notification.displayTab();
    },
    setTab : function(key, counter) {
        if(counter == '') counter = 0;

        if(Notification.tab_counter1_key == key) {
            Notification.tab_counter1 = counter;
        }
        if(Notification.tab_counter2_key == key) {
            Notification.tab_counter2 = counter;
        }
    },
    displayTab : function() {
        if(Notification.tab_counter1 == 0 && Notification.tab_counter2 == 0) {
            document.title = Notification.document_title;

            if(Notification.favicon != null)
                Notification.favicon.badge(0);

            if(Notification.electron != null)
                Notification.electron.notification(false);
        } else {
            document.title = '(' + Notification.tab_counter1 + '/' + Notification.tab_counter2 + ') ' + Notification.document_title;

            if(Notification.favicon != null)
                Notification.favicon.badge(Notification.tab_counter1 + Notification.tab_counter2);

            if(Notification.electron != null)
                Notification.electron.notification(Notification.tab_counter1 + Notification.tab_counter2);
        }
    },
    current : function(key) {
        Notification.notifs_key = key;
        Notification_ajaxCurrent(Notification.notifs_key);
    },
    toast : function(html) {
        // Android notification
        if(typeof Android !== 'undefined') {
            Android.showToast(html);
            return;
        }

        target = document.getElementById('toast');

        if(target) {
            target.innerHTML = html;
        }

        setTimeout(function() {
            target = document.getElementById('toast');
            target.innerHTML = '';
            },
            3000);
    },
    snackbar : function(html, time) {
        if(typeof Android !== 'undefined'
        || Notification.inhibed == true) return;

        target = document.getElementById('snackbar');

        if(target) {
            target.innerHTML = html;
        }

        setTimeout(function() {
            target = document.getElementById('snackbar');
            target.innerHTML = '';
            },
            time*1000);
    },
    desktop : function(title, body, picture, action) {
        if(Notification.inhibed == true
        || Notification.focused
        || typeof DesktopNotification === 'undefined') return;

        var notification = new DesktopNotification(title, { icon: picture, body: body });

        if(action !== null) {
            notification.onclick = function() {
                window.location.href = action;
            }
        }
    },
    android : function(title, body, picture, action) {
        if(typeof Android !== 'undefined') {
            Android.showNotification(title, body, picture, action);
            return;
        }
    }
}

Notification.document_title_init = document.title;

if(typeof MovimWebsocket != 'undefined') {
    MovimWebsocket.attach(function() {
        if(typeof Favico != 'undefined') {
            Notification.favicon = new Favico({
                animation: 'none',
                fontStyle: 'normal',
                bgColor: '#FF5722'
            });
        }

        if(typeof require !== 'undefined') {
            var remote = require('electron').remote;
            Notification.electron = remote.getCurrentWindow();
        }

        Notification.document_title = Notification.document_title_init;
        Notification.tab_counter1 = Notification.tab_counter2 = 0;
        Notification_ajaxGet();
        Notification.current(Notification.notifs_key);
    });
}

document.addEventListener('blur', function() {
    Notification.focused = false;
    Notification_ajaxCurrent('blurred');
});

document.addEventListener('focus', function() {
    Notification.focused = true;
    Notification.current(Notification.notifs_key);
    Notification_ajaxClear(Notification.notifs_key);
});

window.addEventListener('load', function () {
    if(typeof DesktopNotification === 'undefined') return;

    DesktopNotification.requestPermission(function (status) {
    // This allows to use Notification.permission with Chrome/Safari
    if(DesktopNotification.permission !== status) {
        DesktopNotification.permission = status;
    }
  });
});
<commit_msg>Remove console.log<commit_after>var DesktopNotification = Notification;

var Notification = {
    inhibed : false,
    focused : false,
    tab_counter1 : 0,
    tab_counter2 : 0,
    tab_counter1_key : 'chat',
    tab_counter2_key : 'news',
    document_title_init : null,
    document_title : document.title,
    notifs_key : '',
    favicon : null,
    electron : null,

    inhibit : function(sec) {
        Notification.inhibed = true;

        if(sec == null) sec = 5;

        setTimeout(function() {
                Notification.inhibed = false;
            },
            sec*1000);
    },
    refresh : function(keys) {
        var counters = document.querySelectorAll('.counter');
        for(i = 0; i < counters.length; i++) {
            var n = counters[i];
            if(n.dataset.key != null
            && keys[n.dataset.key] != null) {
                n.innerHTML = keys[n.dataset.key];
            }
        }

        for(var key in keys) {
            var counter = keys[key];
            Notification.setTab(key, counter);
        }

        Notification.displayTab();
    },
    counter : function(key, counter) {
        var counters = document.querySelectorAll('.counter');
        for(i = 0; i < counters.length; i++) {
            var n = counters[i];
            if(n.dataset.key != null
            && n.dataset.key == key) {
                n.innerHTML = counter;
            }
        }

        Notification.setTab(key, counter);
        Notification.displayTab();
    },
    setTab : function(key, counter) {
        if(counter == '') counter = 0;

        if(Notification.tab_counter1_key == key) {
            Notification.tab_counter1 = counter;
        }
        if(Notification.tab_counter2_key == key) {
            Notification.tab_counter2 = counter;
        }
    },
    displayTab : function() {
        if(Notification.tab_counter1 == 0 && Notification.tab_counter2 == 0) {
            document.title = Notification.document_title;

            if(Notification.favicon != null)
                Notification.favicon.badge(0);

            if(Notification.electron != null)
                Notification.electron.notification(false);
        } else {
            document.title = '(' + Notification.tab_counter1 + '/' + Notification.tab_counter2 + ') ' + Notification.document_title;

            if(Notification.favicon != null)
                Notification.favicon.badge(Notification.tab_counter1 + Notification.tab_counter2);

            if(Notification.electron != null)
                Notification.electron.notification(Notification.tab_counter1 + Notification.tab_counter2);
        }
    },
    current : function(key) {
        Notification.notifs_key = key;
        Notification_ajaxCurrent(Notification.notifs_key);
    },
    toast : function(html) {
        // Android notification
        if(typeof Android !== 'undefined') {
            Android.showToast(html);
            return;
        }

        target = document.getElementById('toast');

        if(target) {
            target.innerHTML = html;
        }

        setTimeout(function() {
            target = document.getElementById('toast');
            target.innerHTML = '';
            },
            3000);
    },
    snackbar : function(html, time) {
        if(typeof Android !== 'undefined'
        || Notification.inhibed == true) return;

        target = document.getElementById('snackbar');

        if(target) {
            target.innerHTML = html;
        }

        setTimeout(function() {
            target = document.getElementById('snackbar');
            target.innerHTML = '';
            },
            time*1000);
    },
    desktop : function(title, body, picture, action) {
        if(Notification.inhibed == true
        || Notification.focused
        || typeof DesktopNotification === 'undefined') return;

        var notification = new DesktopNotification(title, { icon: picture, body: body });

        if(action !== null) {
            notification.onclick = function() {
                window.location.href = action;
            }
        }
    },
    android : function(title, body, picture, action) {
        if(typeof Android !== 'undefined') {
            Android.showNotification(title, body, picture, action);
            return;
        }
    }
}

Notification.document_title_init = document.title;

if(typeof MovimWebsocket != 'undefined') {
    MovimWebsocket.attach(function() {
        if(typeof Favico != 'undefined') {
            Notification.favicon = new Favico({
                animation: 'none',
                fontStyle: 'normal',
                bgColor: '#FF5722'
            });
        }

        if(typeof require !== 'undefined') {
            var remote = require('electron').remote;
            Notification.electron = remote.getCurrentWindow();
        }

        Notification.document_title = Notification.document_title_init;
        Notification.tab_counter1 = Notification.tab_counter2 = 0;
        Notification_ajaxGet();
        Notification.current(Notification.notifs_key);
    });
}

document.addEventListener('blur', function() {
    Notification.focused = false;
    Notification_ajaxCurrent('blurred');
});

document.addEventListener('focus', function() {
    Notification.focused = true;
    Notification.current(Notification.notifs_key);
    Notification_ajaxClear(Notification.notifs_key);
});

window.addEventListener('load', function () {
    if(typeof DesktopNotification === 'undefined') return;

    DesktopNotification.requestPermission(function (status) {
    // This allows to use Notification.permission with Chrome/Safari
    if(DesktopNotification.permission !== status) {
        DesktopNotification.permission = status;
    }
  });
});
<|endoftext|>


<commit_before>/**
 * model/fancy/localstorage.js
 */

var localStorageModel = baseModel.extend({
    /**
     * To use, extend this model and specify key as a property.
     *
     * For example:
     * var metrics = tbone.models.localStorage.make({ key: 'metrics' });
     * metrics.increment('pageloads');
     * console.log(metrics.query('pageloads'));
     */

    initialize: function () {
        var self = this;
        self.query('', JSON.parse(localStorage[self.key] || "null"));
        self.on('change', function () {
            localStorage[self.key] = JSON.stringify(self.attributes);
        });
    }
});
<commit_msg>Fix localStorage model in minified JS<commit_after>/**
 * model/fancy/localstorage.js
 */

var localStorageModel = baseModel.extend({
    /**
     * To use, extend this model and specify key as a property.
     *
     * For example:
     * var metrics = tbone.models.localStorage.make({ key: 'metrics' });
     * metrics.increment('pageloads');
     * console.log(metrics.query('pageloads'));
     */

    initialize: function () {
        var self = this;
        self['query']('', JSON.parse(localStorage[self['key']] || "null"));
        self['on']('change', function () {
            localStorage[self['key']] = JSON.stringify(self.attributes);
        });
    }
});
<|endoftext|>


<commit_before>/**
 * Created by i.navrotskyj on 09.03.2016.
 */
'use strict';

define(['app', 'modules/cdr/libs/fileSaver', 'async', 'jsZIP-utils', 'jsZIP', 'modules/cdr/cdrModel'], function (app, fileSaver, async, jsZIPUtils, jsZIP) {
    // TODO
    app.directive('elasticExportExcel',function (CdrModel) {
        return {
            restrict: 'AE',
            scope: {
                cdrMapColumns: "=",
                cdrColumns: "=",
                cdrFilter: "=",
                cdrSort: "=",
                cdrProgressExport: "=",
                cdrCountExport: "=",
                cdrRunExport: "="
            },
            link: function (scope, el) {
                scope.cdrProgressExport = 0;
                el.bind('click', function() {
                    if (typeof scope.cdrRunExport == 'function') {
                        scope.cdrRunExport(cdrToExcel)
                    } else {
                        cdrToExcel(scope.cdrMapColumns, scope.cdrColumns, scope.cdrFilter, scope.cdrSort, function (err) {
                            if (err)
                                console.error(err);
                        });
                    }
                });

                var cdrToExcel = function (mapColumns, columns, filter, qs, sort, cb) {
                    var _page = 0,
                        maxNodes = 1000,
                        table = '
',
                        _map = [],
                        scroll = '5m',
                        scrollId = null,
                        allCount = 0,
                        forceStop = false
                        ;

                    var progress = 0;

                    table = setHead(table, mapColumns);
                    table += '
';

                    function onData(err, res) {
                        if (err)
                            return cb(err);

                        if (angular.isArray(res)) {
                            progress += res.length;
                            scope.cdrProgressExport = Math.round(progress * 100 / allCount);
                            table = setRows(table, res);

                            if (allCount - progress < maxNodes) {
                               // maxNodes = allCount - progress;
                            }
                            if (progress === allCount || res.length < maxNodes) {
                                table = endTable(table);
                                tableToExcel(table, 'cdr_' + new Date().toLocaleDateString() + '.xls');
                                scope.cdrProgressExport = 0;
                                return cb();
                            }
                        }

                        CdrModel.scrollElasticData(scroll, scrollId, onData)
                    }

                    // onData();

                    CdrModel.getElasticData(++_page, maxNodes, columns, filter, qs, sort, scroll, function (err, data, total, _scrollId) {
                        if (err)
                            return cb(err);

                        scrollId = _scrollId;
                        allCount = total;
                        onData(null, data);
                    });

                    function endTable (table) {
                        return table += '

'
                    }

                    function setRows (table, rows) {
                        angular.forEach(rows, function (value) {
                            table = setRow(table, value);
                        });
                        return table
                    }

                    function setRow (table, row) {
                        table += '
';
                        angular.forEach(_map, function (col, key) {
                            if (col.noRender) return;
                            table += '' + (col.type === 'timestamp' ? parseTimeStamp((row[col.name] || '')) : (row[col.name] || ''))+ '	';
                        });
                        table += '
';
                        return table;
                    }

                    function parseTimeStamp (timestamp) {
                        // TODO
                        //return '=TEXT(DATE(1970;1;1)+' + timestamp + '/60/60/24/1000/1000;"yyyy-mm-dd hh:mm:ss")'; //
                        return timestamp ? new Date(timestamp).toLocaleString() : '-';
                    }

                    function setHead(table, columns) {
                        table += '

';
                        for (var key in columns) {
                            if (columns[key].noRender) continue;
                            _map.push(columns[key]);
                            table += '' + (columns[key].caption || '') + '	'
                        }
                        table += '

';
                        return table;
                    }
                };

                var tableToExcel = function(table, name){
                    var fullTemplate = "";
                    fullTemplate += '<meta http-equiv="content-type" content="application/vnd.ms-excel; charset=UTF-8">' + table + '';

                    var blob = new Blob([fullTemplate], {
                        // https://github.com/faisalman/simple-excel-js/blob/master/src/simple-excel.js
                        type: "application/octet-stream"
                    });
                    fileSaver(blob, name)
                };
            }
        };
    });

    app.directive('cdrExportExcel',function (CdrModel) {
        return {
            restrict: 'AE',
            scope: {
                cdrMapColumns: "=",
                cdrColumns: "=",
                cdrFilter: "=",
                cdrSort: "=",
                cdrProgressExport: "=",
                cdrCountExport: "=",
                cdrRunExport: "="
            },
            link: function (scope, el) {
                scope.cdrProgressExport = 0;
                el.bind('click', function() {
                    if (typeof scope.cdrRunExport == 'function') {
                        scope.cdrRunExport(cdrToExcel)
                    } else {
                        cdrToExcel(scope.cdrMapColumns, scope.cdrColumns, scope.cdrFilter, scope.cdrSort, function (err) {
                            if (err)
                                console.error(err);
                        });
                    }
                });

                var cdrToExcel = function (mapColumns, columns, filter, sort, cb) {
                    var _page = 0,
                        maxNodes = 1000,
                        table = '
',
                        _map = [],
                        allCount = 0
                        ;

                    var progress = 0;

                    table = setHead(table, mapColumns);
                    table += '
';

                    function onData(err, res) {
                        if (err)
                            return cb(err);

                        if (angular.isArray(res)) {
                            progress += res.length;
                            scope.cdrProgressExport = Math.round(progress * 100 / allCount);
                            table = setRows(table, res);

                            if (allCount - progress < maxNodes) {
                                maxNodes = allCount - progress;
                            }
                            if (progress == allCount || res.length < maxNodes) {
                                table = endTable(table);
                                tableToExcel(table, 'cdr_' + new Date().toLocaleDateString() + '.xls');
                                scope.cdrProgressExport = 0;
                                return cb();
                            }
                        }

                        CdrModel.getData(_page++, maxNodes, columns, filter, sort, onData);
                    }

                    CdrModel.getCount(filter, function (err, count) {
                        if (err)
                            return cb(err);
                        allCount = +count;
                        scope.cdrCountExport = +count;
                        onData();
                    });

                    function endTable (table) {
                        return table += '

'
                    }

                    function setRows (table, rows) {
                        angular.forEach(rows, function (value) {
                            table = setRow(table, value);
                        });
                        return table
                    }

                    function setRow (table, row) {
                        table += '
';
                        angular.forEach(_map, function (col, key) {
                            if (col.value.noRender) return;
                            table += '' + (col.value.type == 'timestamp' ? parseTimeStamp((row[col.id] || '')) : (row[col.id] || ''))+ '	';
                        });
                        table += '
';
                        return table;
                    }

                    function parseTimeStamp (timestamp) {
                        // TODO rus ms-office govno!!!
                        //return '=TEXT(DATE(1970;1;1)+' + timestamp + '/60/60/24/1000/1000;"yyyy-mm-dd hh:mm:ss")'; //
                        return timestamp ? new Date(timestamp / 1000).toLocaleString() : '-';
                    }
                    function setHead(table, columns) {
                        table += '

';
                        for (var key in columns) {
                            if (columns[key].noRender) continue;
                            _map.push({
                                id: key,
                                value: columns[key]
                            });
                            table += '' + (columns[key].caption || '') + '	'
                        }
                        table += '

';
                        return table;
                    }
                };

                var tableToExcel = function(table, name){
                    var fullTemplate = "";
                    fullTemplate += '<meta http-equiv="content-type" content="application/vnd.ms-excel; charset=UTF-8">' + table + '';

                    var blob = new Blob([fullTemplate], {
                        // https://github.com/faisalman/simple-excel-js/blob/master/src/simple-excel.js
                        type: "application/octet-stream"
                    });
                    fileSaver(blob, name)
                };
            }
        };
    });

    app.directive('elasticExportFiles', function (CdrModel, fileModel, notifi) {
        return {
            restrict: 'AE',
            scope: {
                cdrFilter: "=",
                cdrSort: "=",
                cdrProgressExport: "=",
                cdrCountExport: "=",
                cdrRunExport: "="
            },
            link: function (scope, el) {
                el.bind('click', function() {
                    if (typeof scope.cdrRunExport == 'function') {
                        scope.cdrRunExport(exportFiles)
                    } else {
                        exportFiles(scope.cdrFilter, scope.cdrSort, "", function (err) {
                            if (err)
                                console.error(err);
                        });
                    }
                });

                var exportFiles = function (_filter, qs, sort, domain, cb) {
                    var _page = 0,
                        maxNodes = 100,
                        columns = {other: ["uuid"]};

                    if (domain) {
                        columns.domain = domain;
                    }

                    var filter = [_filter, {"exists": {"field": "recordings"}}];

                    var progress = 0;
                    var errorFiles = [];
                    var zip = new jsZIP();

                    // TODO add filter variable exists webitel_record_file_name

                    function loadFiles(arr, cb) {
                        async.eachSeries(
                            arr,
                            function (i, cb) {

                                fileModel.getFiles(i["uuid"].toString(), function (err, files) {

                                    if (!files)
                                        return cb();

                                    async.eachSeries(
                                        files,
                                        function (file, cb) {
                                            var pref = file['content-type'] === "application/pdf" ? "pdf" :"mp3";
                                            var uri = fileModel.getUri(file.uuid, file.name, file["createdOn"], pref);
                                            jsZIPUtils.getBinaryContent(uri, function (e, data) {
                                                if (e) {
                                                    errorFiles.push(e.message);
                                                    return cb();
                                                }
                                                zip.file(file["createdOn"] + '_' + file.name + '.' + pref, data);
                                                cb();
                                            });
                                        },
                                        cb
                                    )

                                });
                            },
                            cb
                        );
                    }

                    function onData(err, res, allCount) {
                        if (err)
                            return cb(err);

                        if (angular.isArray(res)) {
                            progress += res.length;
                            scope.cdrProgressExport = Math.round(progress * 100 / allCount);

                            if (allCount - progress < maxNodes) {
                                // maxNodes = allCount - progress;
                            }
                            if (progress == allCount || res.length < maxNodes) {
                                // END
                                scope.cdrProgressExport = 0;
                                return loadFiles(res, function (e) {
                                    if (e)
                                        return cb(e);

                                    if (errorFiles.length > 0) {
                                        // TODO add show log
                                        notifi.error(new Error('Download files: error count ' + errorFiles.length));
                                    }
                                    zip.generateAsync({type:"blob"}).then(function(content) {
                                        fileSaver(content, "recordFiles.zip");
                                    });
                                    cb();
                                })
                            }

                            loadFiles(res, function (e) {
                                if (e)
                                    return cb(e);
                                CdrModel.getElasticData(++_page, maxNodes, columns, filter, qs, sort, null, onData);
                            });
                        } else {
                            CdrModel.getElasticData(++_page, maxNodes, columns, filter, qs, sort, null, onData);
                        }
                    }

                    onData();

                }
            }
        }
    });

    app.directive('ngJsonExportExcel', function () {
        return {
            restrict: 'AE',
            scope: {
                data : '=',
                filename: '=?',
                reportFields: '=',
                separator: '@'
            },
            link: function (scope, element) {
                scope.filename = !!scope.filename ? scope.filename : 'export-excel';

                var fields = [];
                var header = [];
                var separator = scope.separator || ';';

                angular.forEach(scope.reportFields, function(field, key) {
                    if(!field || !key) {
                        throw new Error('error json report fields');
                    }

                    fields.push(key);
                    header.push(field);
                });

                element.bind('click', function() {
                    var bodyData = _bodyData();
                    var strData = _convertToExcel(bodyData);

                    var blob = new Blob([strData], {type: "text/plain;charset=utf-8"});

                    return saveAs(blob, [scope.filename + '.csv']);
                });

                function _bodyData() {
                    var data = scope.data;
                    var body = "";
                    angular.forEach(data, function(dataItem) {
                        var rowItems = [];

                        angular.forEach(fields, function(field) {
                            if(field.indexOf('.')) {
                                field = field.split(".");
                                var curItem = dataItem;

                                // deep access to obect property
                                angular.forEach(field, function(prop){
                                    if (curItem !== null && curItem !== undefined) {
                                        curItem = curItem[prop];
                                    }
                                });

                                data = curItem;
                            }
                            else {
                                data = dataItem[field];
                            }

                            var fieldValue = data !== null ? data : ' ';

                            if (fieldValue !== undefined && angular.isObject(fieldValue)) {
                                fieldValue = _objectToString(fieldValue);
                            }

                            rowItems.push(fieldValue);
                        });

                        body += rowItems.join(separator) + '\n';
                    });

                    return body;
                }

                function _convertToExcel(body) {
                    return header.join(separator) + '\n' + body;
                }

                function _objectToString(object) {
                    var output = '';
                    angular.forEach(object, function(value, key) {
                        output += key + ':' + value + ' ';
                    });

                    return '"' + output + '"';
                }
            }
        };
    });
});<commit_msg>WTEL-669<commit_after>/**
 * Created by i.navrotskyj on 09.03.2016.
 */
'use strict';

define(['app', 'modules/cdr/libs/fileSaver', 'async', 'jsZIP-utils', 'jsZIP', 'modules/cdr/cdrModel'], function (app, fileSaver, async, jsZIPUtils, jsZIP) {
    // TODO
    app.directive('elasticExportExcel',function (CdrModel) {
        return {
            restrict: 'AE',
            scope: {
                cdrMapColumns: "=",
                cdrColumns: "=",
                cdrFilter: "=",
                cdrSort: "=",
                cdrProgressExport: "=",
                cdrCountExport: "=",
                cdrRunExport: "="
            },
            link: function (scope, el) {
                scope.cdrProgressExport = 0;
                el.bind('click', function() {
                    if (typeof scope.cdrRunExport == 'function') {
                        scope.cdrRunExport(cdrToExcel)
                    } else {
                        cdrToExcel(scope.cdrMapColumns, scope.cdrColumns, scope.cdrFilter, scope.cdrSort, function (err) {
                            if (err)
                                console.error(err);
                        });
                    }
                });

                var cdrToExcel = function (mapColumns, columns, filter, qs, sort, cb) {
                    var _page = 0,
                        maxNodes = 1000,
                        table = '
',
                        _map = [],
                        scroll = '5m',
                        scrollId = null,
                        allCount = 0,
                        forceStop = false
                        ;

                    var progress = 0;

                    table = setHead(table, mapColumns);
                    table += '
';

                    function onData(err, res) {
                        if (err)
                            return cb(err);

                        if (angular.isArray(res)) {
                            progress += res.length;
                            scope.cdrProgressExport = Math.round(progress * 100 / allCount);
                            table = setRows(table, res);

                            if (allCount - progress < maxNodes) {
                               // maxNodes = allCount - progress;
                            }
                            if (progress === allCount || res.length < maxNodes) {
                                table = endTable(table);
                                tableToExcel(table, 'cdr_' + new Date().toLocaleDateString() + '.xls');
                                scope.cdrProgressExport = 0;
                                return cb();
                            }
                        }

                        CdrModel.scrollElasticData(scroll, scrollId, onData)
                    }

                    // onData();

                    CdrModel.getElasticData(++_page, maxNodes, columns, filter, qs, sort, scroll, function (err, data, total, _scrollId) {
                        if (err)
                            return cb(err);

                        scrollId = _scrollId;
                        allCount = total;
                        onData(null, data);
                    });

                    function endTable (table) {
                        return table += '

'
                    }

                    function setRows (table, rows) {
                        angular.forEach(rows, function (value) {
                            table = setRow(table, value);
                        });
                        return table
                    }

                    function setRow (table, row) {
                        table += '
';
                        angular.forEach(_map, function (col, key) {
                            if (col.noRender) return;
                            table += '' + (col.type === 'timestamp' ? parseTimeStamp((row[col.name] || '')) : (row[col.name] || ''))+ '	';
                        });
                        table += '
';
                        return table;
                    }

                    function parseTimeStamp (timestamp) {
                        // TODO
                        //return '=TEXT(DATE(1970;1;1)+' + timestamp + '/60/60/24/1000/1000;"yyyy-mm-dd hh:mm:ss")'; //
                        if (angular.isArray(timestamp)) {
                            timestamp = timestamp[0];
                        }
                        return timestamp ? new Date(timestamp).toLocaleString() : '-';
                    }

                    function setHead(table, columns) {
                        table += '

';
                        for (var key in columns) {
                            if (columns[key].noRender) continue;
                            _map.push(columns[key]);
                            table += '' + (columns[key].caption || '') + '	'
                        }
                        table += '

';
                        return table;
                    }
                };

                var tableToExcel = function(table, name){
                    var fullTemplate = "";
                    fullTemplate += '<meta http-equiv="content-type" content="application/vnd.ms-excel; charset=UTF-8">' + table + '';

                    var blob = new Blob([fullTemplate], {
                        // https://github.com/faisalman/simple-excel-js/blob/master/src/simple-excel.js
                        type: "application/octet-stream"
                    });
                    fileSaver(blob, name)
                };
            }
        };
    });

    app.directive('cdrExportExcel',function (CdrModel) {
        return {
            restrict: 'AE',
            scope: {
                cdrMapColumns: "=",
                cdrColumns: "=",
                cdrFilter: "=",
                cdrSort: "=",
                cdrProgressExport: "=",
                cdrCountExport: "=",
                cdrRunExport: "="
            },
            link: function (scope, el) {
                scope.cdrProgressExport = 0;
                el.bind('click', function() {
                    if (typeof scope.cdrRunExport == 'function') {
                        scope.cdrRunExport(cdrToExcel)
                    } else {
                        cdrToExcel(scope.cdrMapColumns, scope.cdrColumns, scope.cdrFilter, scope.cdrSort, function (err) {
                            if (err)
                                console.error(err);
                        });
                    }
                });

                var cdrToExcel = function (mapColumns, columns, filter, sort, cb) {
                    var _page = 0,
                        maxNodes = 1000,
                        table = '
',
                        _map = [],
                        allCount = 0
                        ;

                    var progress = 0;

                    table = setHead(table, mapColumns);
                    table += '
';

                    function onData(err, res) {
                        if (err)
                            return cb(err);

                        if (angular.isArray(res)) {
                            progress += res.length;
                            scope.cdrProgressExport = Math.round(progress * 100 / allCount);
                            table = setRows(table, res);

                            if (allCount - progress < maxNodes) {
                                maxNodes = allCount - progress;
                            }
                            if (progress == allCount || res.length < maxNodes) {
                                table = endTable(table);
                                tableToExcel(table, 'cdr_' + new Date().toLocaleDateString() + '.xls');
                                scope.cdrProgressExport = 0;
                                return cb();
                            }
                        }

                        CdrModel.getData(_page++, maxNodes, columns, filter, sort, onData);
                    }

                    CdrModel.getCount(filter, function (err, count) {
                        if (err)
                            return cb(err);
                        allCount = +count;
                        scope.cdrCountExport = +count;
                        onData();
                    });

                    function endTable (table) {
                        return table += '

'
                    }

                    function setRows (table, rows) {
                        angular.forEach(rows, function (value) {
                            table = setRow(table, value);
                        });
                        return table
                    }

                    function setRow (table, row) {
                        table += '
';
                        angular.forEach(_map, function (col, key) {
                            if (col.value.noRender) return;
                            table += '' + (col.value.type == 'timestamp' ? parseTimeStamp((row[col.id] || '')) : (row[col.id] || ''))+ '	';
                        });
                        table += '
';
                        return table;
                    }

                    function parseTimeStamp (timestamp) {
                        // TODO rus ms-office govno!!!
                        //return '=TEXT(DATE(1970;1;1)+' + timestamp + '/60/60/24/1000/1000;"yyyy-mm-dd hh:mm:ss")'; //
                        return timestamp ? new Date(timestamp / 1000).toLocaleString() : '-';
                    }
                    function setHead(table, columns) {
                        table += '

';
                        for (var key in columns) {
                            if (columns[key].noRender) continue;
                            _map.push({
                                id: key,
                                value: columns[key]
                            });
                            table += '' + (columns[key].caption || '') + '	'
                        }
                        table += '

';
                        return table;
                    }
                };

                var tableToExcel = function(table, name){
                    var fullTemplate = "";
                    fullTemplate += '<meta http-equiv="content-type" content="application/vnd.ms-excel; charset=UTF-8">' + table + '';

                    var blob = new Blob([fullTemplate], {
                        // https://github.com/faisalman/simple-excel-js/blob/master/src/simple-excel.js
                        type: "application/octet-stream"
                    });
                    fileSaver(blob, name)
                };
            }
        };
    });

    app.directive('elasticExportFiles', function (CdrModel, fileModel, notifi) {
        return {
            restrict: 'AE',
            scope: {
                cdrFilter: "=",
                cdrSort: "=",
                cdrProgressExport: "=",
                cdrCountExport: "=",
                cdrRunExport: "="
            },
            link: function (scope, el) {
                el.bind('click', function() {
                    if (typeof scope.cdrRunExport == 'function') {
                        scope.cdrRunExport(exportFiles)
                    } else {
                        exportFiles(scope.cdrFilter, scope.cdrSort, "", function (err) {
                            if (err)
                                console.error(err);
                        });
                    }
                });

                var exportFiles = function (_filter, qs, sort, domain, cb) {
                    var _page = 0,
                        maxNodes = 100,
                        columns = {other: ["uuid"]};

                    if (domain) {
                        columns.domain = domain;
                    }

                    var filter = [_filter, {"exists": {"field": "recordings"}}];

                    var progress = 0;
                    var errorFiles = [];
                    var zip = new jsZIP();

                    // TODO add filter variable exists webitel_record_file_name

                    function loadFiles(arr, cb) {
                        async.eachSeries(
                            arr,
                            function (i, cb) {

                                fileModel.getFiles(i["uuid"].toString(), function (err, files) {

                                    if (!files)
                                        return cb();

                                    async.eachSeries(
                                        files,
                                        function (file, cb) {
                                            var pref = file['content-type'] === "application/pdf" ? "pdf" :"mp3";
                                            var uri = fileModel.getUri(file.uuid, file.name, file["createdOn"], pref);
                                            jsZIPUtils.getBinaryContent(uri, function (e, data) {
                                                if (e) {
                                                    errorFiles.push(e.message);
                                                    return cb();
                                                }
                                                zip.file(file["createdOn"] + '_' + file.name + '.' + pref, data);
                                                cb();
                                            });
                                        },
                                        cb
                                    )

                                });
                            },
                            cb
                        );
                    }

                    function onData(err, res, allCount) {
                        if (err)
                            return cb(err);

                        if (angular.isArray(res)) {
                            progress += res.length;
                            scope.cdrProgressExport = Math.round(progress * 100 / allCount);

                            if (allCount - progress < maxNodes) {
                                // maxNodes = allCount - progress;
                            }
                            if (progress == allCount || res.length < maxNodes) {
                                // END
                                scope.cdrProgressExport = 0;
                                return loadFiles(res, function (e) {
                                    if (e)
                                        return cb(e);

                                    if (errorFiles.length > 0) {
                                        // TODO add show log
                                        notifi.error(new Error('Download files: error count ' + errorFiles.length));
                                    }
                                    zip.generateAsync({type:"blob"}).then(function(content) {
                                        fileSaver(content, "recordFiles.zip");
                                    });
                                    cb();
                                })
                            }

                            loadFiles(res, function (e) {
                                if (e)
                                    return cb(e);
                                CdrModel.getElasticData(++_page, maxNodes, columns, filter, qs, sort, null, onData);
                            });
                        } else {
                            CdrModel.getElasticData(++_page, maxNodes, columns, filter, qs, sort, null, onData);
                        }
                    }

                    onData();

                }
            }
        }
    });

    app.directive('ngJsonExportExcel', function () {
        return {
            restrict: 'AE',
            scope: {
                data : '=',
                filename: '=?',
                reportFields: '=',
                separator: '@'
            },
            link: function (scope, element) {
                scope.filename = !!scope.filename ? scope.filename : 'export-excel';

                var fields = [];
                var header = [];
                var separator = scope.separator || ';';

                angular.forEach(scope.reportFields, function(field, key) {
                    if(!field || !key) {
                        throw new Error('error json report fields');
                    }

                    fields.push(key);
                    header.push(field);
                });

                element.bind('click', function() {
                    var bodyData = _bodyData();
                    var strData = _convertToExcel(bodyData);

                    var blob = new Blob([strData], {type: "text/plain;charset=utf-8"});

                    return saveAs(blob, [scope.filename + '.csv']);
                });

                function _bodyData() {
                    var data = scope.data;
                    var body = "";
                    angular.forEach(data, function(dataItem) {
                        var rowItems = [];

                        angular.forEach(fields, function(field) {
                            if(field.indexOf('.')) {
                                field = field.split(".");
                                var curItem = dataItem;

                                // deep access to obect property
                                angular.forEach(field, function(prop){
                                    if (curItem !== null && curItem !== undefined) {
                                        curItem = curItem[prop];
                                    }
                                });

                                data = curItem;
                            }
                            else {
                                data = dataItem[field];
                            }

                            var fieldValue = data !== null ? data : ' ';

                            if (fieldValue !== undefined && angular.isObject(fieldValue)) {
                                fieldValue = _objectToString(fieldValue);
                            }

                            rowItems.push(fieldValue);
                        });

                        body += rowItems.join(separator) + '\n';
                    });

                    return body;
                }

                function _convertToExcel(body) {
                    return header.join(separator) + '\n' + body;
                }

                function _objectToString(object) {
                    var output = '';
                    angular.forEach(object, function(value, key) {
                        output += key + ':' + value + ' ';
                    });

                    return '"' + output + '"';
                }
            }
        };
    });
});<|endoftext|>


<commit_before>import React from 'react';

import SPELLS from 'common/SPELLS';
import SpellIcon from 'common/SpellIcon';

import DualStatisticBox, { STATISTIC_ORDER } from 'Main/DualStatisticBox';
import { formatPercentage, formatNumber } from 'common/format';
import Combatants from 'Parser/Core/Modules/Combatants';
import Analyzer from 'Parser/Core/Analyzer';

import calculateEffectiveDamage from 'Parser/Core/calculateEffectiveDamage';
import calculateEffectiveHealing from 'Parser/Core/calculateEffectiveHealing';
import AtonementDamageSource from '../Features/AtonementDamageSource';
import isAtonement from '../Core/isAtonement';
import Atonement from './Atonement';

const SINS_OF_THE_MANY_BASE_BONUS = 0.12;
const SINS_OF_THE_MANY_FLOOR_BONUS = 0.03;

/**
 * Sins allows you to have one Atonement active whilst keeping the full bonus
 * from the passive. Hence this map should be seen as overrides for a linear
 * progression from the max to the floor per Atonement active.
 */
const BONUS_DAMAGE_MAP = {
  1: 0.12,
};

class SinsOfTheMany extends Analyzer {
  static dependencies = {
    combatants: Combatants,
    atonementDamageSource: AtonementDamageSource,
    atonement: Atonement,
  };

  bonusDamage = 0;
  bonusHealing = 0;

  get currentBonus() {
    const baseBonus = SINS_OF_THE_MANY_BASE_BONUS * 100;
    const floorBonus = SINS_OF_THE_MANY_FLOOR_BONUS * 100;
    const activeBuffs = this.atonement.numAtonementsActive;

    // Return an override, if necessary
    if (BONUS_DAMAGE_MAP[activeBuffs]) return BONUS_DAMAGE_MAP[activeBuffs];

    // Return the floor if we're below it
    if (floorBonus >= baseBonus - activeBuffs) {
      return SINS_OF_THE_MANY_FLOOR_BONUS;
    }

    // Return the calculated bonus
    return (baseBonus - activeBuffs) / 100;
  }

  /**
   * Sins of the Many buffs all of your damage, there is no whitelist
   */
  on_byPlayer_damage(event) {
    this.bonusDamage += calculateEffectiveDamage(event, this.currentBonus);
  }

  /**
   * This is whitelisted by virtue of Atonement naturally not occuring
   * from abilities not in the whitelist
   */
  on_byPlayer_heal(event) {
    if (!isAtonement(event)) {
      return;
    }

    this.bonusHealing += calculateEffectiveHealing(event, this.currentBonus);
  }

  statistic() {
    return (
      <DualStatisticBox
        icon={<SpellIcon id={SPELLS.SINS_OF_THE_MANY_TALENT.id} />}
        values={[
          `${formatNumber(
            (this.bonusHealing / this.owner.fightDuration) * 1000
          )} HPS`,
          `${formatNumber(
            (this.bonusDamage /
              this.owner.fightDuration) *
              1000
          )} DPS`,
        ]}
        footer={
          <dfn
            data-tip={`
              The effective healing contributed by Sins of the Many was ${formatPercentage(
                this.owner.getPercentageOfTotalHealingDone(this.bonusHealing)
              )}% of total healing done.

              The direct damage contributed by Sins of the Many was ${formatPercentage(
                this.owner.getPercentageOfTotalDamageDone(this.bonusDamage)
              )}% of total damage done.
            `}
          >
            Sins of the Many Output Details
          </dfn>
        }
      />
    );
  }
  statisticOrder = STATISTIC_ORDER.OPTIONAL();
}

export default SinsOfTheMany;
<commit_msg>Include pet damage<commit_after>import React from 'react';

import SPELLS from 'common/SPELLS';
import SpellIcon from 'common/SpellIcon';

import DualStatisticBox, { STATISTIC_ORDER } from 'Main/DualStatisticBox';
import { formatPercentage, formatNumber } from 'common/format';
import Combatants from 'Parser/Core/Modules/Combatants';
import Analyzer from 'Parser/Core/Analyzer';

import calculateEffectiveDamage from 'Parser/Core/calculateEffectiveDamage';
import calculateEffectiveHealing from 'Parser/Core/calculateEffectiveHealing';
import isAtonement from '../Core/isAtonement';
import Atonement from './Atonement';

const SINS_OF_THE_MANY_BASE_BONUS = 0.12;
const SINS_OF_THE_MANY_FLOOR_BONUS = 0.03;

/**
 * Sins allows you to have one Atonement active whilst keeping the full bonus
 * from the passive. Hence this map should be seen as overrides for a linear
 * progression from the max to the floor per Atonement active.
 */
const BONUS_DAMAGE_MAP = {
  1: 0.12,
};

class SinsOfTheMany extends Analyzer {
  static dependencies = {
    combatants: Combatants,
    atonement: Atonement,
  };

  bonusDamage = 0;
  bonusHealing = 0;

  get currentBonus() {
    const baseBonus = SINS_OF_THE_MANY_BASE_BONUS * 100;
    const floorBonus = SINS_OF_THE_MANY_FLOOR_BONUS * 100;
    const activeBuffs = this.atonement.numAtonementsActive;

    // Return an override, if necessary
    if (BONUS_DAMAGE_MAP[activeBuffs]) return BONUS_DAMAGE_MAP[activeBuffs];

    // Return the floor if we're below it
    if (floorBonus >= baseBonus - activeBuffs) {
      return SINS_OF_THE_MANY_FLOOR_BONUS;
    }

    // Return the calculated bonus
    return (baseBonus - activeBuffs) / 100;
  }

  /**
   * Sins of the Many buffs all of your damage, there is no whitelist
   */
  on_byPlayer_damage(event) {
    this.bonusDamage += calculateEffectiveDamage(event, this.currentBonus);
  }

  on_byPlayerPet_damage(event) {
    this.bonusDamage += calculateEffectiveDamage(event, this.currentBonus);
  }

  /**
   * This is whitelisted by virtue of Atonement naturally not occuring
   * from abilities not in the whitelist.
   */
  on_byPlayer_heal(event) {
    if (!isAtonement(event)) {
      return;
    }

    this.bonusHealing += calculateEffectiveHealing(event, this.currentBonus);
  }

  statistic() {
    return (
      <DualStatisticBox
        icon={<SpellIcon id={SPELLS.SINS_OF_THE_MANY_TALENT.id} />}
        values={[
          `${formatNumber(
            (this.bonusHealing / this.owner.fightDuration) * 1000
          )} HPS`,
          `${formatNumber(
            (this.bonusDamage /
              this.owner.fightDuration) *
              1000
          )} DPS`,
        ]}
        footer={
          <dfn
            data-tip={`
              The effective healing contributed by Sins of the Many was ${formatPercentage(
                this.owner.getPercentageOfTotalHealingDone(this.bonusHealing)
              )}% of total healing done.

              The direct damage contributed by Sins of the Many was ${formatPercentage(
                this.owner.getPercentageOfTotalDamageDone(this.bonusDamage)
              )}% of total damage done.
            `}
          >
            Sins of the Many Output Details
          </dfn>
        }
      />
    );
  }
  statisticOrder = STATISTIC_ORDER.OPTIONAL();
}

export default SinsOfTheMany;
<|endoftext|>


<commit_before>// CL API integration with the Grist API
// Docs: https://europepmc.org/GristAPI
// Fields you can search by: https://europepmc.org/GristAPI#API

// Example, get info by grant ID: http://www.ebi.ac.uk/europepmc/GristAPI/rest/get/query=gid:088130&resultType=core&format=json
// Use case: To get the name of a Principal Investigator, call CLapi.internals.use.grist.grant_id(the_grant_id).data.Person
//           Will return {FamilyName: "Friston", GivenName: "Karl", Initials: "KJ", Title: "Prof"}

CLapi.addRoute('/use/grist', {
    get: {
        action: function () {
            var routes = [];
            for ( var k in CLapi.internals.use.grist ) routes.push(k);
            return {status: 'success', routes: routes, data: {info: 'returns a subset of the Grist API functionality'} };
        }
    }
});

CLapi.addRoute('use/grist/grant_id/:qry', {
    get: {
        action: function() {
            var res = CLapi.internals.use.grist.grant_id(this.urlParams.qry);
            try {
                return {status: 'success', data: res.data.resultList.result[0] }
            } catch(err) {
                return {status: 'success', data: res.data }
            }
        }
    }
});

CLapi.internals.use.grist.grant_id = function(grant_id) {
    var res = CLapi.internals.use.grist.search('gid:' + grant_id);
    if (res.total > 0) {
        return {status: 'success', data: res.data[0] }
    } else {
        return {status: 'success', data: res }
    }
};

CLapi.internals.use.grist.search = function(qrystr,from,page) {
    const GRIST_API_PAGE_SIZE = 25;  // it's hardcoded to 25 according to the docs
    // note in Grist API one of the params is resultType, in EPMC REST API the same param is resulttype .
    var url = 'http://www.ebi.ac.uk/europepmc/GristAPI/rest/get/query=' + qrystr + '&resultType=core&format=json';
    if (from !== undefined) url += '&page=' + (Math.floor(from/GRIST_API_PAGE_SIZE)+1);
    var res = Meteor.http.call('GET', url);
    return { status: 'success', total: res.data.HitCount, data: res.data.RecordList.Record};  // RecordList is an object?!
};<commit_msg>fix app crashing blunder<commit_after>// CL API integration with the Grist API
// Docs: https://europepmc.org/GristAPI
// Fields you can search by: https://europepmc.org/GristAPI#API

// Example, get info by grant ID: http://www.ebi.ac.uk/europepmc/GristAPI/rest/get/query=gid:088130&resultType=core&format=json
// Use case: To get the name of a Principal Investigator, call CLapi.internals.use.grist.grant_id(the_grant_id).data.Person
//           Will return {FamilyName: "Friston", GivenName: "Karl", Initials: "KJ", Title: "Prof"}

CLapi.addRoute('/use/grist', {
    get: {
        action: function () {
            var routes = [];
            for ( var k in CLapi.internals.use.grist ) routes.push(k);
            return {status: 'success', routes: routes, data: {info: 'returns a subset of the Grist API functionality'} };
        }
    }
});

CLapi.addRoute('use/grist/grant_id/:qry', {
    get: {
        action: function() {
            var res = CLapi.internals.use.grist.grant_id(this.urlParams.qry);
            try {
                return {status: 'success', data: res.data.resultList.result[0] }
            } catch(err) {
                return {status: 'success', data: res.data }
            }
        }
    }
});

CLapi.internals.use.grist = {};

CLapi.internals.use.grist.grant_id = function(grant_id) {
    var res = CLapi.internals.use.grist.search('gid:' + grant_id);
    if (res.total > 0) {
        return {status: 'success', data: res.data[0] }
    } else {
        return {status: 'success', data: res }
    }
};

CLapi.internals.use.grist.search = function(qrystr,from,page) {
    const GRIST_API_PAGE_SIZE = 25;  // it's hardcoded to 25 according to the docs
    // note in Grist API one of the params is resultType, in EPMC REST API the same param is resulttype .
    var url = 'http://www.ebi.ac.uk/europepmc/GristAPI/rest/get/query=' + qrystr + '&resultType=core&format=json';
    if (from !== undefined) url += '&page=' + (Math.floor(from/GRIST_API_PAGE_SIZE)+1);
    var res = Meteor.http.call('GET', url);
    return { status: 'success', total: res.data.HitCount, data: res.data.RecordList.Record};  // RecordList is an object?!
};<|endoftext|>