<commit_before>/**
 * The Alchemy helper
 *
 * @author   Jelle De Loecker   <jelle@develry.be>
 * @since    0.0.1
 * @version  1.0.0
 *
 * @param    {ViewRender}    view
 */
var Alchemy = Function.inherits('Alchemy.Helper', function Alchemy(view) {
	Alchemy.super.call(this, view);
});

/**
 * Function to execute on the client side, when the scene is made
 *
 * @author   Jelle De Loecker   <jelle@develry.be>
 * @since    0.2.0
 * @version  1.0.7
 *
 * @param    {Scene}   scene
 * @param    {Object}  options
 */
Alchemy.setStatic(function onScene(scene, options) {
	window.alchemy.initScene(scene, options);
});

/**
 * Perform a resource request
 *
 * @author   Jelle De Loecker   <jelle@develry.be>
 * @since    0.0.1
 * @version  1.1.0
 *
 * @param    {String|Object}   options
 * @param    {Object}          data
 * @param    {Function}        callback
 *
 * @return   {Pledge}
 */
Alchemy.setMethod(function getResource(options, data, callback) {

	var that = this,
	    conduit,
	    config,
	    pledge,
	    url;

	if (typeof options == 'string') {

		if (options.indexOf('/') > -1) {
			options = {
				href : options
			};
		} else {
			options = {
				name : options
			};
		}
	} else if (options instanceof Classes.RURL) {
		options = {
			href : options
		};
	}

	function resolvePledge(err, result) {

		if (err) {
			return pledge.reject(err);
		}

		pledge.resolve(result);
	}

	if (Blast.isNode) {
		conduit = this.view.server_var('conduit');

		if (!conduit) {
			pledge = Classes.Pledge.reject(new Error('Could not find conduit, alchemy resource will not be fetched'));
			pledge.done(callback);
			return pledge;
		}

		if (typeof data == 'function') {
			callback = data;
			data = null;
		} else {
			options.params = data;
		}

		pledge = new Classes.Pledge();
		pledge.done(callback);

		conduit.loopback(options, resolvePledge);

		return pledge;
	}

	if (typeof data == 'function') {
		callback = data;
		data = null;
	}

	if (options.href) {
		url = options.href;
	} else {

		// See if this is a socket route
		config = this.view.helpers.Router.routeConfig(options.name, true);

		if (config && config.socket_route) {
			pledge = new Classes.Pledge();
			pledge.done(callback);

			// In this case the "alchemy" variable points to the window.alchemy object
			alchemy.submit(config.name, data, resolvePledge);

			return pledge;
		}

		// Get the url to the resource
		url = hawkejs.scene.helpers.Router.routeUrl(options.name, options.params);

		if (!url && typeof name == 'string') {
			url = hawkejs.scene.helpers.Router.routeUrl('APIResource', {name: options.name});
		}

		if (!url) {
			pledge = Classes.Pledge.reject(new Error('No URL could be found for route "' + options.name + '"'));
			pledge.done(callback);
			return pledge;
		}
	}

	options.href = url;

	if (data) {
		options.get = data;
	}

	pledge = hawkejs.scene.fetch(options);
	pledge.done(callback);

	return pledge;
});

/**
 * Register & recompile a callback
 *
 * @author        Jelle De Loecker   <jelle@develry.be>
 * @since         0.2.0
 * @version       0.2.0
 *
 * @param         {Function}   callback
 *
 * @return        {Function}
 */
Alchemy.setMethod(function registerCallback(callback) {

	if (!this.callbacks) {
		this.callbacks = {};
	}

	// The callback will need to be recompiled
	if (!this.callbacks[callback.name]) {
		this.callbacks[callback.name] = this.view.hawkejs.compile({

			// The function that will be re-compiled
			compiled: callback,

			// Template name
			template_name: 'callback_' + callback.name,

			// It's a single function that needs to be called with the 'group_arg' var
			call: 'group_arg',

			// Make sure these variables are available in the scope
			scope: this.view.functionScopes.slice(0)
		});
	}

	return this.callbacks[callback.name];
});

/**
 * Register a group and possible id
 *
 * @author        Jelle De Loecker   <jelle@develry.be>
 * @since         0.2.0
 * @version       0.2.0
 */
Alchemy.setMethod(function registerGroup(name, id, callback) {

	// Make sure the groups exist
	if (!this.groups) {
		this.groups = {};
	}

	if (!this.groups[name]) {
		this.groups[name] = {
			state: 'new',
			hinder: null,
			ids: []
		};
	}

	if (id && !this.groups[name].ids[id]) {
		this.groups[name].ids[id] = [];
	}

	if (callback) {
		this.registerCallback(callback);
		this.groups[name].ids[id].push(callback);
	}
});

/**
 * Get the group data
 *
 * @author        Jelle De Loecker   <jelle@develry.be>
 * @since         0.2.0
 * @version       0.2.0
 */
Alchemy.setMethod(function getGroupData(name, callback) {

	var that = this,
	    group;

	group = this.groups[name];

	if (!group.hinder) {
		group.hinder = Function.hinder(function getData(done) {
			that.getResource(name, {ids: Object.keys(group.ids)}, done);
		});
	}

	if (callback) group.hinder.push(callback);
});

/**
 * Aggregate data.
 * The callback needs to be named and be unique per scope structure
 *
 * @author        Jelle De Loecker   <jelle@develry.be>
 * @since         0.2.0
 * @version       0.2.0
 */
Alchemy.setMethod(function group(name, id, callback) {

	var that = this,
	    scope;

	// Keep reference to the current scope
	scope = this.view.functionScopes.slice(0);

	// Register the group and callback
	this.registerGroup(name, id, callback);

	// Return an async placeholder
	this.view.async(function doAsync(next) {
		that.getGroupData(name, function gotData(err, data) {

			var id_data;

			if (err) {
				return next(err);
			}

			if (data) {
				id_data = data[id];
			}

			that.view.hawkejs.render(that.registerCallback(callback), {__scope: scope, group_arg: id_data}, next);
		});
	});
});

/**
 * Print a segment
 *
 * @author   Jelle De Loecker   <jelle@develry.be>
 * @since    0.5.0
 * @version  0.5.0
 *
 * @param    {String|Object}   options
 * @param    {Object}          data
 */
Alchemy.setMethod(function segment(options, data) {

	var that = this,
	    root;

	if (typeof options == 'string') {
		options = {
			name : options
		};
	}

	// Return an async placeholder
	root = this.view.async(function doAsync(next) {

		var conduit,
		    route,
		    el;

		if (Blast.isNode) {
			conduit = that.view.server_var('conduit');

			if (!conduit) {
				return next();
			}

			options.params = data;

			conduit.loopback(options, next);

			return;
		}

		// @TODO: implement a cleaner way of doing this
		// A lot of the attributes are missing
		el = document.createElement('x-hawkejs');
		el.classList.add('x-hawkejs');
		el.classList.add('js-he-newblock');
		el.dataset.segmentRoute = options.name;
		el.dataset.type = 'element';
		root.element = el;

		// Get the route configuration
		route = that.view.helpers.Router.routeUrl(options.name);

		hawkejs.scene.openUrl(route, {get: data, history: false, root: root}, function done(err, result) {

			if (err) {
				return next(err);
			}

			next(null, el.outerHTML);
		});
	});
});

/**
 * Get the current locale
 *
 * @author   Jelle De Loecker   <jelle@develry.be>
 * @since    1.1.0
 * @version  1.1.0
 *
 * @return   {String}
 */
Alchemy.setMethod(function getLocale() {

	var locales = this.view_render.expose('locales');

	if (locales && locales[0]) {
		return locales[0];
	}

	return 'en';
});

if (!Blast.isBrowser) {
	return;
}

// Send a message to the server when we unload the page
window.addEventListener('unload', function(event) {
	if (console) {
		console.log('Unloading the page ...');
	}
});<commit_msg>Fix data parameters not being passed correctly to the `Alchemy#getResource` helper<commit_after>/**
 * The Alchemy helper
 *
 * @author   Jelle De Loecker   <jelle@develry.be>
 * @since    0.0.1
 * @version  1.0.0
 *
 * @param    {ViewRender}    view
 */
var Alchemy = Function.inherits('Alchemy.Helper', function Alchemy(view) {
	Alchemy.super.call(this, view);
});

/**
 * Function to execute on the client side, when the scene is made
 *
 * @author   Jelle De Loecker   <jelle@develry.be>
 * @since    0.2.0
 * @version  1.0.7
 *
 * @param    {Scene}   scene
 * @param    {Object}  options
 */
Alchemy.setStatic(function onScene(scene, options) {
	window.alchemy.initScene(scene, options);
});

/**
 * Perform a resource request
 *
 * @author   Jelle De Loecker   <jelle@develry.be>
 * @since    0.0.1
 * @version  1.1.0
 *
 * @param    {String|Object}   options
 * @param    {Object}          data
 * @param    {Function}        callback
 *
 * @return   {Pledge}
 */
Alchemy.setMethod(function getResource(options, data, callback) {

	var that = this,
	    conduit,
	    config,
	    pledge,
	    url;

	if (typeof options == 'string') {

		if (options.indexOf('/') > -1) {
			options = {
				href : options
			};
		} else {
			options = {
				name : options
			};
		}
	} else if (options instanceof Classes.RURL) {
		options = {
			href : options
		};
	}

	function resolvePledge(err, result) {

		if (err) {
			return pledge.reject(err);
		}

		pledge.resolve(result);
	}

	if (typeof data == 'function') {
		callback = data;
		data = null;
	} else {
		options.params = data;
	}

	if (Blast.isNode) {
		conduit = this.view.server_var('conduit');

		if (!conduit) {
			pledge = Classes.Pledge.reject(new Error('Could not find conduit, alchemy resource will not be fetched'));
			pledge.done(callback);
			return pledge;
		}

		pledge = new Classes.Pledge();
		pledge.done(callback);

		conduit.loopback(options, resolvePledge);

		return pledge;
	}

	if (options.href) {
		url = options.href;
	} else {

		// See if this is a socket route
		config = this.view.helpers.Router.routeConfig(options.name, true);

		if (config && config.socket_route) {
			pledge = new Classes.Pledge();
			pledge.done(callback);

			// In this case the "alchemy" variable points to the window.alchemy object
			alchemy.submit(config.name, data, resolvePledge);

			return pledge;
		}

		// Get the url to the resource
		url = hawkejs.scene.helpers.Router.routeUrl(options.name, options.params);

		if (!url && typeof name == 'string') {
			url = hawkejs.scene.helpers.Router.routeUrl('APIResource', {name: options.name});
		}

		if (!url) {
			pledge = Classes.Pledge.reject(new Error('No URL could be found for route "' + options.name + '"'));
			pledge.done(callback);
			return pledge;
		}
	}

	options.href = url;

	if (data) {
		options.get = data;
	}

	pledge = hawkejs.scene.fetch(options);
	pledge.done(callback);

	return pledge;
});

/**
 * Register & recompile a callback
 *
 * @author        Jelle De Loecker   <jelle@develry.be>
 * @since         0.2.0
 * @version       0.2.0
 *
 * @param         {Function}   callback
 *
 * @return        {Function}
 */
Alchemy.setMethod(function registerCallback(callback) {

	if (!this.callbacks) {
		this.callbacks = {};
	}

	// The callback will need to be recompiled
	if (!this.callbacks[callback.name]) {
		this.callbacks[callback.name] = this.view.hawkejs.compile({

			// The function that will be re-compiled
			compiled: callback,

			// Template name
			template_name: 'callback_' + callback.name,

			// It's a single function that needs to be called with the 'group_arg' var
			call: 'group_arg',

			// Make sure these variables are available in the scope
			scope: this.view.functionScopes.slice(0)
		});
	}

	return this.callbacks[callback.name];
});

/**
 * Register a group and possible id
 *
 * @author        Jelle De Loecker   <jelle@develry.be>
 * @since         0.2.0
 * @version       0.2.0
 */
Alchemy.setMethod(function registerGroup(name, id, callback) {

	// Make sure the groups exist
	if (!this.groups) {
		this.groups = {};
	}

	if (!this.groups[name]) {
		this.groups[name] = {
			state: 'new',
			hinder: null,
			ids: []
		};
	}

	if (id && !this.groups[name].ids[id]) {
		this.groups[name].ids[id] = [];
	}

	if (callback) {
		this.registerCallback(callback);
		this.groups[name].ids[id].push(callback);
	}
});

/**
 * Get the group data
 *
 * @author        Jelle De Loecker   <jelle@develry.be>
 * @since         0.2.0
 * @version       0.2.0
 */
Alchemy.setMethod(function getGroupData(name, callback) {

	var that = this,
	    group;

	group = this.groups[name];

	if (!group.hinder) {
		group.hinder = Function.hinder(function getData(done) {
			that.getResource(name, {ids: Object.keys(group.ids)}, done);
		});
	}

	if (callback) group.hinder.push(callback);
});

/**
 * Aggregate data.
 * The callback needs to be named and be unique per scope structure
 *
 * @author        Jelle De Loecker   <jelle@develry.be>
 * @since         0.2.0
 * @version       0.2.0
 */
Alchemy.setMethod(function group(name, id, callback) {

	var that = this,
	    scope;

	// Keep reference to the current scope
	scope = this.view.functionScopes.slice(0);

	// Register the group and callback
	this.registerGroup(name, id, callback);

	// Return an async placeholder
	this.view.async(function doAsync(next) {
		that.getGroupData(name, function gotData(err, data) {

			var id_data;

			if (err) {
				return next(err);
			}

			if (data) {
				id_data = data[id];
			}

			that.view.hawkejs.render(that.registerCallback(callback), {__scope: scope, group_arg: id_data}, next);
		});
	});
});

/**
 * Print a segment
 *
 * @author   Jelle De Loecker   <jelle@develry.be>
 * @since    0.5.0
 * @version  0.5.0
 *
 * @param    {String|Object}   options
 * @param    {Object}          data
 */
Alchemy.setMethod(function segment(options, data) {

	var that = this,
	    root;

	if (typeof options == 'string') {
		options = {
			name : options
		};
	}

	// Return an async placeholder
	root = this.view.async(function doAsync(next) {

		var conduit,
		    route,
		    el;

		if (Blast.isNode) {
			conduit = that.view.server_var('conduit');

			if (!conduit) {
				return next();
			}

			options.params = data;

			conduit.loopback(options, next);

			return;
		}

		// @TODO: implement a cleaner way of doing this
		// A lot of the attributes are missing
		el = document.createElement('x-hawkejs');
		el.classList.add('x-hawkejs');
		el.classList.add('js-he-newblock');
		el.dataset.segmentRoute = options.name;
		el.dataset.type = 'element';
		root.element = el;

		// Get the route configuration
		route = that.view.helpers.Router.routeUrl(options.name);

		hawkejs.scene.openUrl(route, {get: data, history: false, root: root}, function done(err, result) {

			if (err) {
				return next(err);
			}

			next(null, el.outerHTML);
		});
	});
});

/**
 * Get the current locale
 *
 * @author   Jelle De Loecker   <jelle@develry.be>
 * @since    1.1.0
 * @version  1.1.0
 *
 * @return   {String}
 */
Alchemy.setMethod(function getLocale() {

	var locales = this.view_render.expose('locales');

	if (locales && locales[0]) {
		return locales[0];
	}

	return 'en';
});

if (!Blast.isBrowser) {
	return;
}

// Send a message to the server when we unload the page
window.addEventListener('unload', function(event) {
	if (console) {
		console.log('Unloading the page ...');
	}
});<|endoftext|>


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

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

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

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

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

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

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

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

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

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

  L.tail = l0;
  return circle;
}

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

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

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

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

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

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

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

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

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

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

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

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

  L.tail = l0;
  return circle;
}

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

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

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


<commit_before>define(
  'ephox.polaris.api.Regexes',

  [
    'global!RegExp'
  ],

  function (RegExp) {
    var link = function () {
     /* http://blog.mattheworiordan.com/post/13174566389/url-regular-expression-for-links-with-or-without-the
        Modified to:
        - include port numbers
        - allow full stops in email addresses
        - allow -_.~*+=!&;:'%@?^${}()\w+, after the #
        - allow -_.~*+=!&;:'%@?^${}()\w+, after the ?
        - move allow -_.~*+=!&;:'%@?^${}() in email usernames to the first @ match (TBIO-4809)
        - enforce domains to be [A-Za-z0-9-]+(?:\.[A-Za-z0-9-]+)+ so they can't end in a period (TBIO-4809)
        - removed a bunch of escaping, made every group non-capturing (during TBIO-4809)

      (?:
        (?:[A-Za-z]{3,9}:(?:\/\/)?)
        (?:[\-;:&=.+$,\w_~*+=!&;:'%@?^${}(),]+@)?
        [A-Za-z0-9-]+(?:\.[A-Za-z0-9-]+)*
        |
          (?:www\.
          |
            [-;:&=+$,\w.]+@)
          [A-Za-z0-9-]+(?:\.[A-Za-z0-9-]+)*
      )
      (?::[0-9]+)?
      (?:\/[+~%\/.()\w-_]*)?
      (?:\?(?:[\-_.~*+=!&;:'%@?^${}()\w,]*))?
      (?:#(?:[\-_.~*+=!&;:'%@?^${}()\w,\/]*))?

      */

      return /(?:(?:[A-Za-z]{3,9}:(?:\/\/)?)(?:[\-;:&=.+$,\w_~*+=!&;:'%@?^${}(),]+@)?[A-Za-z0-9-]+(?:\.[A-Za-z0-9-]+)*|(?:www\.|[-;:&=+$,\w.]+@)[A-Za-z0-9-]+(?:\.[A-Za-z0-9-]+)*)(?::[0-9]+)?(?:\/[+~%\/.()\w-_]*)?(?:\?(?:[-_.~*+=!&;:'%@?^${}()\w,]*))?(?:#(?:[-_.~*+=!&;:'%@?^${}()\w,\/]*))?/g;
    };

    var autolink = function () {
      /*
       * Takes the above link, and makes two additions:
       *
       * - allows punctuation at the end (so it can be used for TBIO autolink macro)
       * - wraps the link regex in a group so that match[1] returns the desired contents
       */
      var linksource = link().source;
      return new RegExp('(' + linksource + ')[\-_.~*+=!&;:\'%@?^${}(),]*', 'g');
    };

    var tokens = function (value, parameters) {
      return value.replace(/\{(\d+)\}/g, function (match, contents, offset, s) {
        var index = parseInt(contents, 10);
        if (parameters[index] === undefined) throw 'No value for token: ' + match + ' in translation: ' + value;
        return parameters[index];
      });
    };

    return {
      tokens: tokens,
      link: link,
      autolink: autolink
    };
  }
);<commit_msg>TBIO-4809: Update comment with note about performance<commit_after>define(
  'ephox.polaris.api.Regexes',

  [
    'global!RegExp'
  ],

  function (RegExp) {
    var link = function () {
     /* http://blog.mattheworiordan.com/post/13174566389/url-regular-expression-for-links-with-or-without-the
        Modified to:
        - include port numbers
        - allow full stops in email addresses
        - allow -_.~*+=!&;:'%@?^${}()\w+, after the #
        - allow -_.~*+=!&;:'%@?^${}()\w+, after the ?
        - move allow -_.~*+=!&;:'%@?^${}() in email usernames to the first @ match (TBIO-4809)
        - enforce domains to be [A-Za-z0-9-]+(?:\.[A-Za-z0-9-]+)+ so they can't end in a period (TBIO-4809)
        - removed a bunch of escaping, made every group non-capturing (during TBIO-4809)

      (?:
        (?:[A-Za-z]{3,9}:(?:\/\/)?)
        (?:[\-;:&=.+$,\w_~*+=!&;:'%@?^${}(),]+@)?
        [A-Za-z0-9-]+(?:\.[A-Za-z0-9-]+)*
        |
          (?:www\.
          |
            [-;:&=+$,\w.]+@)
          [A-Za-z0-9-]+(?:\.[A-Za-z0-9-]+)*
      )
      (?::[0-9]+)?
      (?:\/[+~%\/.()\w-_]*)?
      (?:\?(?:[\-_.~*+=!&;:'%@?^${}()\w,]*))?
      (?:#(?:[\-_.~*+=!&;:'%@?^${}()\w,\/]*))?

      */

      return /(?:(?:[A-Za-z]{3,9}:(?:\/\/)?)(?:[\-;:&=.+$,\w_~*+=!&;:'%@?^${}(),]+@)?[A-Za-z0-9-]+(?:\.[A-Za-z0-9-]+)*|(?:www\.|[-;:&=+$,\w.]+@)[A-Za-z0-9-]+(?:\.[A-Za-z0-9-]+)*)(?::[0-9]+)?(?:\/[+~%\/.()\w-_]*)?(?:\?(?:[-_.~*+=!&;:'%@?^${}()\w,]*))?(?:#(?:[-_.~*+=!&;:'%@?^${}()\w,\/]*))?/g;
    };

    var autolink = function () {
      /*
       * Takes the link regex, and makes two additions:
       *
       * - allows punctuation at the end (so it can be used for TBIO autolink macro)
       * - wraps the link regex in a group so that match[1] returns the desired contents
       *
       * We may need to inline the link regex if this refactoring technique causes performance issues; we're assuming browsers can optimise the above regex but not this style.
       * TBIO calls this method every time space or enter is pressed.
       */
      var linksource = link().source;
      return new RegExp('(' + linksource + ')[\-_.~*+=!&;:\'%@?^${}(),]*', 'g');
    };

    var tokens = function (value, parameters) {
      return value.replace(/\{(\d+)\}/g, function (match, contents, offset, s) {
        var index = parseInt(contents, 10);
        if (parameters[index] === undefined) throw 'No value for token: ' + match + ' in translation: ' + value;
        return parameters[index];
      });
    };

    return {
      tokens: tokens,
      link: link,
      autolink: autolink
    };
  }
);<|endoftext|>


<commit_before>var calendarEvents = [];

var currentOptions = {};

var calendarChannelOptions = {
	bookings: true,
	staffAbsences: true
};

function setupCalendar(selector, onSelect, viewOptions) {
	var cal = selector.show().fullCalendar({
		// basic appearance
		header: {
			left: 'prev,next today',
			center: 'title',
			right: ''
		},
		defaultView: 'agendaWeek',
		selectable: true,
		selectHelper: true,
		allDaySlot: false,
		timeFormat: 'HH:mm',
		weekends: true,
		slotMinutes: 15,

		// set data source
		events: calendarEvents,

		// TODO
		minTime: "08:00:00",
		maxTime: "19:00:00",

		// what to display?
		viewDisplay: function (e) {
			// clear bookings
			calendarEvents.length = 0;

			// reload for new date range
			updateCalendar(selector, e.start, e.end, viewOptions);

			// resize
			var v = this;
			e.setHeight($(window).height() - $(v).position().top - 60);
			setTimeout(function () {
				e.setHeight($(window).height() - $(v).position().top - 60);
			}, 500);
		},

		// on-select function
		select: onSelect,

		// pop-up with details
		eventRender: function (event, element) {
			element.addClass(event.type);

			element.popover({
				title: event.title,
				placement: 'auto',
				html: true,
				trigger: 'hover',
				animation: 'true',
				content: event.msg,
				container: 'body'
			});

			// click listener to hide
			$('body').on('click', function (e) {
				if (!element.is(e.target) && element.has(e.target).length === 0
					&& $('.popover').has(e.target).length === 0)
					element.popover('hide');
			});
		},

		eventClick: function (calEvent, jsEvent, view) {
			if (calEvent.url && viewOptions['linkEvents']) {
				window.location.href = calEvent.url;
			}
			return false;
		},

		windowResize: function (calView) {
			calView.setHeight($(window).height() - $(this).position().top - 60);
		}
	});

	// add loading icon and toggle buttons
	cal.find('.fc-header-right').html('' +
	'' +
	'' +
	'    ' +
	'Loading...' +
	'    ' +
	'' +
	'' +
	'<button class="btn btn-primary calendar-channel-toggle" data-target="staffAbsences">Absences</button>' +
	'  ' +
	'<button class="btn btn-primary calendar-channel-toggle" data-target="bookings">Bookings</button>' +
	'');

	// perform action for toggle buttons
	$('.calendar-channel-toggle').click(function (e) {
		e.preventDefault();

		// get target
		var target = $(this).data('target');

		// switch button classes
		if (calendarChannelOptions[target]) {
			$(this).removeClass('btn-primary').addClass('btn-default');
		} else {
			$(this).removeClass('btn-default').addClass('btn-primary');
		}

		// change option
		calendarChannelOptions[target] = !calendarChannelOptions[target];

		// redraw
		calendarEvents.length = 0;
		updateCalendar(
			currentOptions['selector'],
			currentOptions['startDate'],
			currentOptions['endDate'],
			currentOptions['options']
		);

		// drop focus
		$(this).blur();
	});

	return cal;
}

function updateCalendar(selector, startDate, endDate, options) {
	// store current options
	currentOptions['selector'] = selector;
	currentOptions['startDate'] = startDate;
	currentOptions['endDate'] = endDate;
	currentOptions['options'] = options;

	// show loading message
	$('.calendar-loading-msg').show();
	$('.calendar-channel-filters').hide();

	// adjust end date backwards by one
	endDate = new Date(((endDate.getTime()) - 86400000));

	// get start/end strings to pass to calendar data route
	var startDateString = startDate.getFullYear()
		+ '-'
		+ (startDate.getMonth() < 10 ? '0' : '') + (startDate.getMonth() + 1)
		+ '-'
		+ ((startDate.getDate()) < 10 ? '0' : '') + (startDate.getDate());
	var endDateString = endDate.getFullYear()
		+ '-'
		+ (endDate.getMonth() < 10 ? '0' : '') + (endDate.getMonth() + 1)
		+ '-'
		+ ((endDate.getDate()) < 10 ? '0' : '') + (endDate.getDate());

	// build URL
	var url = '/calendar-data?start=' + startDateString + '&end=' + endDateString;
	for (var key in options) url += '&' + key + '=' + (options[key] === true ? '1' : options[key]);
	for (key in calendarChannelOptions) url += '&' + key + '=' + (calendarChannelOptions[key] === true ? '1' : calendarChannelOptions[key]);

	// send AJAX call
	$.get(url)
		.done(function (result) {
			var rawJson = result.toString();
			var parsedJson = JSON.parse(rawJson);

			// loop through bookings
			if (calendarChannelOptions['bookings'] && typeof(parsedJson.bookings) != "undefined") {
				var bookingTitle, bookingCameraType, bookingStart, bookingEnd;
				for (var i = 0; i < parsedJson.bookings.length; ++i) {
					for (var j = 0; j < parsedJson.bookings[i].bookingSections.length; ++j) {
						// build title
						bookingTitle = parsedJson.bookings[i].therapyName + ":\n" + parsedJson.bookings[i].patientName;

						// build camera type
						bookingCameraType = parsedJson.bookings[i].cameraName;

						// start and end time
						bookingStart = parsedJson.bookings[i].bookingSections[j].startTime + ":00";
						bookingStart = bookingStart.replace(" ", "T");
						bookingEnd = parsedJson.bookings[i].bookingSections[j].endTime + ":00";
						bookingEnd = bookingEnd.replace(" ", "T");

						// add event
						calendarEvents.push({
							title: bookingTitle,
							start: bookingStart,
							end: bookingEnd,
							msg: "" +
							"Start time: " + parsedJson.bookings[i].bookingSections[j].startTime.substring(10, 16) + ""
							+ "
" +
							"End time: " + parsedJson.bookings[i].bookingSections[j].endTime.substring(10, 16) + ""
							+ "
" + bookingCameraType,
							allDay: false,
							url: '/booking-details/' + parsedJson.bookings[i].id,
							type: 'booking'
						});
					}
				}
			}

			// loop through absences
			if (calendarChannelOptions['staffAbsences'] && typeof(parsedJson.staffAbsences) != "undefined") {
				var absenceTitle, absenceStart, absenceEnd;
				for (i = 0; i < parsedJson.staffAbsences.length; ++i) {
					// build title
					absenceTitle = "Absent: " + parsedJson.staffAbsences[i].staffName;

					// start and end time
					absenceStart = parsedJson.staffAbsences[i].from + ":00";
					absenceStart = absenceStart.replace(" ", "T");
					absenceEnd = parsedJson.staffAbsences[i].to + ":00";
					absenceEnd = absenceEnd.replace(" ", "T");

					// add event
					calendarEvents.push({
						title: absenceTitle,
						start: absenceStart,
						end: absenceEnd,
						msg: "" +
						"Start time: " + parsedJson.staffAbsences[i].from.substring(10, 16) + "" +
						"
" +
						"End time: " + parsedJson.staffAbsences[i].to.substring(10, 16) + "",
						allDay: false,
						type: 'absence'
					});
				}
			}

			// update events
			selector.fullCalendar('refetchEvents');

			// hide loading message
			$('.calendar-loading-msg').hide();
			$('.calendar-channel-filters').removeClass('hide').show();
		})
		.fail(function (xhr, textStatus, errorThrown) {
			toastr.error("Failed to load calendar data.")
			$('.calendar-loading-msg').hide();
		}
	);
}<commit_msg>Switched to checkboxes<commit_after>var calendarEvents = [];

var currentOptions = {};

var calendarChannelOptions = {
	bookings: true,
	staffAbsences: true
};

function setupCalendar(selector, onSelect, viewOptions) {
	var cal = selector.show().fullCalendar({
		// basic appearance
		header: {
			left: 'prev,next today',
			center: 'title',
			right: ''
		},
		defaultView: 'agendaWeek',
		selectable: true,
		selectHelper: true,
		allDaySlot: false,
		timeFormat: 'HH:mm',
		weekends: true,
		slotMinutes: 15,

		// set data source
		events: calendarEvents,

		// TODO
		minTime: "08:00:00",
		maxTime: "19:00:00",

		// what to display?
		viewDisplay: function (e) {
			// clear bookings
			calendarEvents.length = 0;

			// reload for new date range
			updateCalendar(selector, e.start, e.end, viewOptions);

			// resize
			var v = this;
			e.setHeight($(window).height() - $(v).position().top - 60);
			setTimeout(function () {
				e.setHeight($(window).height() - $(v).position().top - 60);
			}, 500);
		},

		// on-select function
		select: onSelect,

		// pop-up with details
		eventRender: function (event, element) {
			element.addClass(event.type);

			element.popover({
				title: event.title,
				placement: 'auto',
				html: true,
				trigger: 'hover',
				animation: 'true',
				content: event.msg,
				container: 'body'
			});

			// click listener to hide
			$('body').on('click', function (e) {
				if (!element.is(e.target) && element.has(e.target).length === 0
					&& $('.popover').has(e.target).length === 0)
					element.popover('hide');
			});
		},

		eventClick: function (calEvent, jsEvent, view) {
			if (calEvent.url && viewOptions['linkEvents']) {
				window.location.href = calEvent.url;
			}
			return false;
		},

		windowResize: function (calView) {
			calView.setHeight($(window).height() - $(this).position().top - 60);
		}
	});

	// add loading icon and toggle buttons
	cal.find('.fc-header-right').html('' +
	'' +
	'' +
	'    ' +
	'Loading...' +
	'    ' +
	'' +
	'' +
	'<button class="btn btn-default calendar-channel-toggle" data-target="staffAbsences"> Absences</button>' +
	'  ' +
	'<button class="btn btn-default calendar-channel-toggle" data-target="bookings"> Bookings</button>' +
	'');

	// perform action for toggle buttons
	$('.calendar-channel-toggle').click(function (e) {
		e.preventDefault();

		// get target
		var target = $(this).data('target');

		// switch button classes
		if (calendarChannelOptions[target]) {
			$(this).find('i').removeClass('fa-check-square-o').addClass('fa-square-o');
		} else {
			$(this).find('i').removeClass('fa-square-o').addClass('fa-check-square-o');
		}

		// change option
		calendarChannelOptions[target] = !calendarChannelOptions[target];

		// redraw
		calendarEvents.length = 0;
		updateCalendar(
			currentOptions['selector'],
			currentOptions['startDate'],
			currentOptions['endDate'],
			currentOptions['options']
		);

		// drop focus
		$(this).blur();
	});

	return cal;
}

function updateCalendar(selector, startDate, endDate, options) {
	// store current options
	currentOptions['selector'] = selector;
	currentOptions['startDate'] = startDate;
	currentOptions['endDate'] = endDate;
	currentOptions['options'] = options;

	// show loading message
	$('.calendar-loading-msg').show();
	$('.calendar-channel-filters').hide();

	// adjust end date backwards by one
	endDate = new Date(((endDate.getTime()) - 86400000));

	// get start/end strings to pass to calendar data route
	var startDateString = startDate.getFullYear()
		+ '-'
		+ (startDate.getMonth() < 10 ? '0' : '') + (startDate.getMonth() + 1)
		+ '-'
		+ ((startDate.getDate()) < 10 ? '0' : '') + (startDate.getDate());
	var endDateString = endDate.getFullYear()
		+ '-'
		+ (endDate.getMonth() < 10 ? '0' : '') + (endDate.getMonth() + 1)
		+ '-'
		+ ((endDate.getDate()) < 10 ? '0' : '') + (endDate.getDate());

	// build URL
	var url = '/calendar-data?start=' + startDateString + '&end=' + endDateString;
	for (var key in options) url += '&' + key + '=' + (options[key] === true ? '1' : options[key]);
	for (key in calendarChannelOptions) url += '&' + key + '=' + (calendarChannelOptions[key] === true ? '1' : calendarChannelOptions[key]);

	// send AJAX call
	$.get(url)
		.done(function (result) {
			var rawJson = result.toString();
			var parsedJson = JSON.parse(rawJson);

			// loop through bookings
			if (calendarChannelOptions['bookings'] && typeof(parsedJson.bookings) != "undefined") {
				var bookingTitle, bookingCameraType, bookingStart, bookingEnd;
				for (var i = 0; i < parsedJson.bookings.length; ++i) {
					for (var j = 0; j < parsedJson.bookings[i].bookingSections.length; ++j) {
						// build title
						bookingTitle = parsedJson.bookings[i].therapyName + ":\n" + parsedJson.bookings[i].patientName;

						// build camera type
						bookingCameraType = parsedJson.bookings[i].cameraName;

						// start and end time
						bookingStart = parsedJson.bookings[i].bookingSections[j].startTime + ":00";
						bookingStart = bookingStart.replace(" ", "T");
						bookingEnd = parsedJson.bookings[i].bookingSections[j].endTime + ":00";
						bookingEnd = bookingEnd.replace(" ", "T");

						// add event
						calendarEvents.push({
							title: bookingTitle,
							start: bookingStart,
							end: bookingEnd,
							msg: "" +
							"Start time: " + parsedJson.bookings[i].bookingSections[j].startTime.substring(10, 16) + ""
							+ "
" +
							"End time: " + parsedJson.bookings[i].bookingSections[j].endTime.substring(10, 16) + ""
							+ "
" + bookingCameraType,
							allDay: false,
							url: '/booking-details/' + parsedJson.bookings[i].id,
							type: 'booking'
						});
					}
				}
			}

			// loop through absences
			if (calendarChannelOptions['staffAbsences'] && typeof(parsedJson.staffAbsences) != "undefined") {
				var absenceTitle, absenceStart, absenceEnd;
				for (i = 0; i < parsedJson.staffAbsences.length; ++i) {
					// build title
					absenceTitle = "Absent: " + parsedJson.staffAbsences[i].staffName;

					// start and end time
					absenceStart = parsedJson.staffAbsences[i].from + ":00";
					absenceStart = absenceStart.replace(" ", "T");
					absenceEnd = parsedJson.staffAbsences[i].to + ":00";
					absenceEnd = absenceEnd.replace(" ", "T");

					// add event
					calendarEvents.push({
						title: absenceTitle,
						start: absenceStart,
						end: absenceEnd,
						msg: "" +
						"Start time: " + parsedJson.staffAbsences[i].from.substring(10, 16) + "" +
						"
" +
						"End time: " + parsedJson.staffAbsences[i].to.substring(10, 16) + "",
						allDay: false,
						type: 'absence'
					});
				}
			}

			// update events
			selector.fullCalendar('refetchEvents');

			// hide loading message
			$('.calendar-loading-msg').hide();
			$('.calendar-channel-filters').removeClass('hide').show();
		})
		.fail(function (xhr, textStatus, errorThrown) {
			toastr.error("Failed to load calendar data.")
			$('.calendar-loading-msg').hide();
		}
	);
}<|endoftext|>


<commit_before>var calendarEvents = [];

var currentOptions = {};

var selectedCameras = null;

var calendarChannelOptions = {
	bookings: true,
	staffAbsences: true,
	genericEvents: true
};

function setupCalendar(selector, onSelect, viewOptions) {
	var cal = selector.show().fullCalendar({
		// basic appearance
		header: {
			left: 'prev,next today',
			center: 'title',
			right: ''
		},
		defaultView: 'agendaWeek',
		selectable: viewOptions['selectable'],
		selectHelper: true,
		allDaySlot: false,
		timeFormat: 'HH:mm',
		weekends: true,
		slotMinutes: 15,

		// set data source
		events: calendarEvents,

		// TODO
		minTime: "08:00:00",
		maxTime: "19:00:00",

		// what to display?
		viewDisplay: function (e) {
			// clear bookings
			calendarEvents.length = 0;

			// reload for new date range
			updateCalendar(selector, e.start, e.end, viewOptions);

			// resize
			var v = this;
			e.setHeight($(window).height() - $(v).position().top - 60);
			setTimeout(function () {
				e.setHeight($(window).height() - $(v).position().top - 60);
			}, 500);
		},

		// on-select function
		select: onSelect,

		// pop-up with details
		eventRender: function (event, element) {
			element.addClass(event.type);

			element.popover({
				title: event.title,
				placement: 'auto',
				html: true,
				trigger: 'hover',
				animation: 'true',
				content: event.msg,
				container: 'body'
			});

			// click listener to hide
			$('body').on('click', function (e) {
				if (!element.is(e.target) && element.has(e.target).length === 0
					&& $('.popover').has(e.target).length === 0)
					element.popover('hide');
			});
		},

		eventClick: function (calEvent, jsEvent, view) {
			if (calEvent.url && viewOptions['linkEvents']) {
				window.location.href = calEvent.url;
			}
			return false;
		},

		windowResize: function (calView) {
			calView.setHeight($(window).height() - $(this).position().top - 60);
		}
	});

	// add loading icon and toggle buttons
	cal.find('.fc-header-right').html('' +
	'' +
	'' +
	'    ' +
	'' +
	'' +
	'<button class="btn btn-default calendar-channel-toggle" data-target="staffAbsences"> Absences</button>' +
	'  ' +
	'<button class="btn btn-default calendar-channel-toggle" data-target="genericEvents"> Events</button>' +
	'  ' +
	'<button class="btn btn-default calendar-channel-cameras"> Camera Use</button>' +
	'');

	// perform action for toggle buttons
	$('.calendar-channel-toggle').click(function (e) {
		e.preventDefault();

		// get target
		var target = $(this).data('target');

		// switch button classes
		if (calendarChannelOptions[target]) {
			$(this).find('i').removeClass('fa-check-square-o').addClass('fa-square-o');
		} else {
			$(this).find('i').removeClass('fa-square-o').addClass('fa-check-square-o');
		}

		// change option
		calendarChannelOptions[target] = !calendarChannelOptions[target];

		// redraw
		calendarEvents.length = 0;
		updateCalendar(
			currentOptions['selector'],
			currentOptions['startDate'],
			currentOptions['endDate'],
			currentOptions['options']
		);

		// drop focus
		$(this).blur();
	});

	// perform action for camera selection buttons
	$('.calendar-channel-cameras').click(function (e) {
		e.preventDefault();
		openCameraSelectModal();
	});

	return cal;
}

function updateCalendar(selector, startDate, endDate, options) {
	// store current options
	currentOptions['selector'] = selector;
	currentOptions['startDate'] = startDate;
	currentOptions['endDate'] = endDate;
	currentOptions['options'] = options;

	// show loading message
	setLoading(true, selector);

	// adjust end date backwards by one
	endDate = new Date(((endDate.getTime()) - 86400000));

	// get start/end strings to pass to calendar data route
	var startDateString = startDate.getFullYear()
		+ '-'
		+ (startDate.getMonth() < 10 ? '0' : '') + (startDate.getMonth() + 1)
		+ '-'
		+ ((startDate.getDate()) < 10 ? '0' : '') + (startDate.getDate());
	var endDateString = endDate.getFullYear()
		+ '-'
		+ (endDate.getMonth() < 10 ? '0' : '') + (endDate.getMonth() + 1)
		+ '-'
		+ ((endDate.getDate()) < 10 ? '0' : '') + (endDate.getDate());

	// build URL
	var url = '/calendar-data?start=' + startDateString + '&end=' + endDateString;
	for (var key in options) url += '&' + key + '=' + (options[key] === true ? '1' : options[key]);
	for (key in calendarChannelOptions) url += '&' + key + '=' + (calendarChannelOptions[key] === true ? '1' : calendarChannelOptions[key]);
	url += '&cameras=';
	if (selectedCameras == null) {
		// default to all
		url += 'all';
	} else {
		url += selectedCameras.join(',');
	}

	// send AJAX call
	$.get(url)
		.done(function (result) {
			var rawJson = result.toString();
			var parsedJson = JSON.parse(rawJson);

			// loop through bookings
			if (calendarChannelOptions['bookings'] && typeof(parsedJson.bookings) != "undefined") {
				var bookingTitle, bookingCameraType, bookingStart, bookingEnd;
				for (var i = 0; i < parsedJson.bookings.length; ++i) {
					for (var j = 0; j < parsedJson.bookings[i].bookingSections.length; ++j) {
						// build title
						bookingTitle = parsedJson.bookings[i].therapyName + ":\n" + parsedJson.bookings[i].patientName;

						// build camera type
						bookingCameraType = parsedJson.bookings[i].cameraName;

						// start and end time
						bookingStart = parsedJson.bookings[i].bookingSections[j].startTime + ":00";
						bookingStart = bookingStart.replace(" ", "T");
						bookingEnd = parsedJson.bookings[i].bookingSections[j].endTime + ":00";
						bookingEnd = bookingEnd.replace(" ", "T");

						// add event
						calendarEvents.push({
							title: bookingTitle,
							start: bookingStart,
							end: bookingEnd,
							msg: "" +
							"Start time: " + parsedJson.bookings[i].bookingSections[j].startTime.substring(10, 16) + ""
							+ "
" +
							"End time: " + parsedJson.bookings[i].bookingSections[j].endTime.substring(10, 16) + ""
							+ "
" + bookingCameraType,
							allDay: false,
							url: '/booking-details/' + parsedJson.bookings[i].id,
							type: 'booking booking-' + parsedJson.bookings[i].colourNumber
						});
					}
				}
			}

			// loop through absences
			if (calendarChannelOptions['staffAbsences'] && typeof(parsedJson.staffAbsences) != "undefined") {
				var absenceTitle, absenceStart, absenceEnd;
				for (i = 0; i < parsedJson.staffAbsences.length; ++i) {
					// build title
					absenceTitle = "Absent: " + parsedJson.staffAbsences[i].staffName;

					// start and end time
					absenceStart = parsedJson.staffAbsences[i].from + ":00";
					absenceStart = absenceStart.replace(" ", "T");
					absenceEnd = parsedJson.staffAbsences[i].to + ":00";
					absenceEnd = absenceEnd.replace(" ", "T");

					// add event
					calendarEvents.push({
						title: absenceTitle,
						start: absenceStart,
						end: absenceEnd,
						msg: "" +
						"Start time: " + parsedJson.staffAbsences[i].from.substring(10, 16) + "" +
						"
" +
						"End time: " + parsedJson.staffAbsences[i].to.substring(10, 16) + "",
						allDay: false,
						type: 'absence'
					});
				}
			}

			// loop through events
			if (calendarChannelOptions['genericEvents'] && typeof(parsedJson.genericEvents) != "undefined") {
				var eventTitle, eventDesc, eventStart, eventEnd;
				for (i = 0; i < parsedJson.genericEvents.length; ++i) {
					// build title and desc
					eventTitle = parsedJson.genericEvents[i].title;
					eventDesc = parsedJson.genericEvents[i].description;

					// start and end time
					eventStart = parsedJson.genericEvents[i].from + ":00";
					eventStart = eventStart.replace(" ", "T");
					eventEnd = parsedJson.genericEvents[i].to + ":00";
					eventEnd = eventEnd.replace(" ", "T");

					// add event
					calendarEvents.push({
						title: eventTitle,
						start: eventStart,
						end: eventEnd,
						msg: "" +
						"Start time: " + parsedJson.genericEvents[i].from.substring(10, 16) + "" +
						"
" +
						"End time: " + parsedJson.genericEvents[i].to.substring(10, 16) + "" +
						"
" + eventDesc,
						allDay: false,
						type: 'generic-event'
					});
				}
			}

			// update events
			selector.fullCalendar('refetchEvents');

			// hide loading message
			setLoading(false, selector);
		})
		.fail(function (xhr, textStatus, errorThrown) {
			toastr.error("Failed to load calendar data.");
			$('.calendar-loading-msg').hide();
		}
	);
}

function openCameraSelectModal() {
	var modal = $('.camera-select-modal');

	modal.removeClass('hide').modal({
		backdrop: 'static',
		keyboard: false
	});

	modal.find("input:checkbox").each(function(i, e) {
		var id = $(e).attr('id');
		for (i in selectedCameras) {
			if (id == "camera-" + selectedCameras[i]) {
				$(e).prop('checked', true);
				return;
			}
		}
		$(e).prop('checked', false);
	});

	$('.btn-update').unbind('click').click(function (e) {
		// get selected
		selectedCameras = $('.selected-cameras:checked').map(function () {
			return this.value;
		}).get();

		// redraw
		calendarEvents.length = 0;
		updateCalendar(
			currentOptions['selector'],
			currentOptions['startDate'],
			currentOptions['endDate'],
			currentOptions['options']
		);

		// close modal
		modal.modal('hide');
	});

	$('.btn-cancel').unbind('click').click(function (e) {
		modal.modal('hide');
	});
}

function setLoading(loading, calendar) {
	if (loading) {
		$('.calendar-loading-msg').show();
		$('.calendar-channel-filters').find('button').prop('disabled', true);
		calendar.fadeTo(300, 0.4);
	} else {
		$('.calendar-loading-msg').hide();
		$('.calendar-channel-filters').removeClass('hide').show();
		$('.calendar-channel-filters').find('button').prop('disabled', false);
		calendar.fadeTo(300, 1.0);
	}
}<commit_msg>Automatically preselects the cameras<commit_after>var calendarEvents = [];

var currentOptions = {};

var selectedCameras = null;

var calendarChannelOptions = {
	bookings: true,
	staffAbsences: true,
	genericEvents: true
};

function setupCalendar(selector, onSelect, viewOptions) {
	var cal = selector.show().fullCalendar({
		// basic appearance
		header: {
			left: 'prev,next today',
			center: 'title',
			right: ''
		},
		defaultView: 'agendaWeek',
		selectable: viewOptions['selectable'],
		selectHelper: true,
		allDaySlot: false,
		timeFormat: 'HH:mm',
		weekends: true,
		slotMinutes: 15,

		// set data source
		events: calendarEvents,

		// TODO
		minTime: "08:00:00",
		maxTime: "19:00:00",

		// what to display?
		viewDisplay: function (e) {
			// clear bookings
			calendarEvents.length = 0;

			// reload for new date range
			updateCalendar(selector, e.start, e.end, viewOptions);

			// resize
			var v = this;
			e.setHeight($(window).height() - $(v).position().top - 60);
			setTimeout(function () {
				e.setHeight($(window).height() - $(v).position().top - 60);
			}, 500);
		},

		// on-select function
		select: onSelect,

		// pop-up with details
		eventRender: function (event, element) {
			element.addClass(event.type);

			element.popover({
				title: event.title,
				placement: 'auto',
				html: true,
				trigger: 'hover',
				animation: 'true',
				content: event.msg,
				container: 'body'
			});

			// click listener to hide
			$('body').on('click', function (e) {
				if (!element.is(e.target) && element.has(e.target).length === 0
					&& $('.popover').has(e.target).length === 0)
					element.popover('hide');
			});
		},

		eventClick: function (calEvent, jsEvent, view) {
			if (calEvent.url && viewOptions['linkEvents']) {
				window.location.href = calEvent.url;
			}
			return false;
		},

		windowResize: function (calView) {
			calView.setHeight($(window).height() - $(this).position().top - 60);
		}
	});

	// add loading icon and toggle buttons
	cal.find('.fc-header-right').html('' +
	'' +
	'' +
	'    ' +
	'' +
	'' +
	'<button class="btn btn-default calendar-channel-toggle" data-target="staffAbsences"> Absences</button>' +
	'  ' +
	'<button class="btn btn-default calendar-channel-toggle" data-target="genericEvents"> Events</button>' +
	'  ' +
	'<button class="btn btn-default calendar-channel-cameras"> Camera Use</button>' +
	'');

	// perform action for toggle buttons
	$('.calendar-channel-toggle').click(function (e) {
		e.preventDefault();

		// get target
		var target = $(this).data('target');

		// switch button classes
		if (calendarChannelOptions[target]) {
			$(this).find('i').removeClass('fa-check-square-o').addClass('fa-square-o');
		} else {
			$(this).find('i').removeClass('fa-square-o').addClass('fa-check-square-o');
		}

		// change option
		calendarChannelOptions[target] = !calendarChannelOptions[target];

		// redraw
		calendarEvents.length = 0;
		updateCalendar(
			currentOptions['selector'],
			currentOptions['startDate'],
			currentOptions['endDate'],
			currentOptions['options']
		);

		// drop focus
		$(this).blur();
	});

	// perform action for camera selection buttons
	$('.calendar-channel-cameras').click(function (e) {
		e.preventDefault();
		openCameraSelectModal();
	});

	return cal;
}

function updateCalendar(selector, startDate, endDate, options) {
	// store current options
	currentOptions['selector'] = selector;
	currentOptions['startDate'] = startDate;
	currentOptions['endDate'] = endDate;
	currentOptions['options'] = options;

	// show loading message
	setLoading(true, selector);

	// adjust end date backwards by one
	endDate = new Date(((endDate.getTime()) - 86400000));

	// get start/end strings to pass to calendar data route
	var startDateString = startDate.getFullYear()
		+ '-'
		+ (startDate.getMonth() < 10 ? '0' : '') + (startDate.getMonth() + 1)
		+ '-'
		+ ((startDate.getDate()) < 10 ? '0' : '') + (startDate.getDate());
	var endDateString = endDate.getFullYear()
		+ '-'
		+ (endDate.getMonth() < 10 ? '0' : '') + (endDate.getMonth() + 1)
		+ '-'
		+ ((endDate.getDate()) < 10 ? '0' : '') + (endDate.getDate());

	// build URL
	var url = '/calendar-data?start=' + startDateString + '&end=' + endDateString;
	for (var key in options) url += '&' + key + '=' + (options[key] === true ? '1' : options[key]);
	for (key in calendarChannelOptions) url += '&' + key + '=' + (calendarChannelOptions[key] === true ? '1' : calendarChannelOptions[key]);
	url += '&cameras=';
	if (selectedCameras == null) {
		// default to all
		url += 'all';
	} else {
		url += selectedCameras.join(',');
	}

	// send AJAX call
	$.get(url)
		.done(function (result) {
			var rawJson = result.toString();
			var parsedJson = JSON.parse(rawJson);

			// loop through bookings
			if (calendarChannelOptions['bookings'] && typeof(parsedJson.bookings) != "undefined") {
				var bookingTitle, bookingCameraType, bookingStart, bookingEnd;
				for (var i = 0; i < parsedJson.bookings.length; ++i) {
					for (var j = 0; j < parsedJson.bookings[i].bookingSections.length; ++j) {
						// build title
						bookingTitle = parsedJson.bookings[i].therapyName + ":\n" + parsedJson.bookings[i].patientName;

						// build camera type
						bookingCameraType = parsedJson.bookings[i].cameraName;

						// start and end time
						bookingStart = parsedJson.bookings[i].bookingSections[j].startTime + ":00";
						bookingStart = bookingStart.replace(" ", "T");
						bookingEnd = parsedJson.bookings[i].bookingSections[j].endTime + ":00";
						bookingEnd = bookingEnd.replace(" ", "T");

						// add event
						calendarEvents.push({
							title: bookingTitle,
							start: bookingStart,
							end: bookingEnd,
							msg: "" +
							"Start time: " + parsedJson.bookings[i].bookingSections[j].startTime.substring(10, 16) + ""
							+ "
" +
							"End time: " + parsedJson.bookings[i].bookingSections[j].endTime.substring(10, 16) + ""
							+ "
" + bookingCameraType,
							allDay: false,
							url: '/booking-details/' + parsedJson.bookings[i].id,
							type: 'booking booking-' + parsedJson.bookings[i].colourNumber
						});
					}
				}
			}

			// loop through absences
			if (calendarChannelOptions['staffAbsences'] && typeof(parsedJson.staffAbsences) != "undefined") {
				var absenceTitle, absenceStart, absenceEnd;
				for (i = 0; i < parsedJson.staffAbsences.length; ++i) {
					// build title
					absenceTitle = "Absent: " + parsedJson.staffAbsences[i].staffName;

					// start and end time
					absenceStart = parsedJson.staffAbsences[i].from + ":00";
					absenceStart = absenceStart.replace(" ", "T");
					absenceEnd = parsedJson.staffAbsences[i].to + ":00";
					absenceEnd = absenceEnd.replace(" ", "T");

					// add event
					calendarEvents.push({
						title: absenceTitle,
						start: absenceStart,
						end: absenceEnd,
						msg: "" +
						"Start time: " + parsedJson.staffAbsences[i].from.substring(10, 16) + "" +
						"
" +
						"End time: " + parsedJson.staffAbsences[i].to.substring(10, 16) + "",
						allDay: false,
						type: 'absence'
					});
				}
			}

			// loop through events
			if (calendarChannelOptions['genericEvents'] && typeof(parsedJson.genericEvents) != "undefined") {
				var eventTitle, eventDesc, eventStart, eventEnd;
				for (i = 0; i < parsedJson.genericEvents.length; ++i) {
					// build title and desc
					eventTitle = parsedJson.genericEvents[i].title;
					eventDesc = parsedJson.genericEvents[i].description;

					// start and end time
					eventStart = parsedJson.genericEvents[i].from + ":00";
					eventStart = eventStart.replace(" ", "T");
					eventEnd = parsedJson.genericEvents[i].to + ":00";
					eventEnd = eventEnd.replace(" ", "T");

					// add event
					calendarEvents.push({
						title: eventTitle,
						start: eventStart,
						end: eventEnd,
						msg: "" +
						"Start time: " + parsedJson.genericEvents[i].from.substring(10, 16) + "" +
						"
" +
						"End time: " + parsedJson.genericEvents[i].to.substring(10, 16) + "" +
						"
" + eventDesc,
						allDay: false,
						type: 'generic-event'
					});
				}
			}

			// update events
			selector.fullCalendar('refetchEvents');

			// hide loading message
			setLoading(false, selector);
		})
		.fail(function (xhr, textStatus, errorThrown) {
			toastr.error("Failed to load calendar data.");
			$('.calendar-loading-msg').hide();
		}
	);
}

function openCameraSelectModal() {
	var modal = $('.camera-select-modal');

	modal.removeClass('hide').modal({
		backdrop: 'static',
		keyboard: false
	});

	modal.find("input:checkbox").each(function (i, e) {
		if (selectedCameras == null) {
			$(e).prop('checked', true);
			return;
		}
		var id = $(e).attr('id');
		for (i in selectedCameras) {
			if (id == "camera-" + selectedCameras[i]) {
				$(e).prop('checked', true);
				return;
			}
		}
		$(e).prop('checked', false);
	});

	$('.btn-update').unbind('click').click(function (e) {
		// get selected
		selectedCameras = $('.selected-cameras:checked').map(function () {
			return this.value;
		}).get();

		// redraw
		calendarEvents.length = 0;
		updateCalendar(
			currentOptions['selector'],
			currentOptions['startDate'],
			currentOptions['endDate'],
			currentOptions['options']
		);

		// close modal
		modal.modal('hide');
	});

	$('.btn-cancel').unbind('click').click(function (e) {
		modal.modal('hide');
	});
}

function setLoading(loading, calendar) {
	if (loading) {
		$('.calendar-loading-msg').show();
		$('.calendar-channel-filters').find('button').prop('disabled', true);
		calendar.fadeTo(300, 0.4);
	} else {
		$('.calendar-loading-msg').hide();
		$('.calendar-channel-filters').removeClass('hide').show();
		$('.calendar-channel-filters').find('button').prop('disabled', false);
		calendar.fadeTo(300, 1.0);
	}
}<|endoftext|>


<commit_before>/**
 * Created by Navi on 19/02/2015.
 */

$(function() {
    $( "#DOB" ).datepicker();
});

$(document).ready(function(){
    $('#addNew').on('click',addNewRow);
});

$(document).ready(function() {
    $("#deletePatients").click(function () {
        $("table input[type ='checkbox']:checked").parent().parent().remove();

    });

    $('#searchPatient').keyup(function () {
        var data = this.value.split(" ");
        var rows = $("#patientInfo tbody tr").hide();
        if(this.value ==""){
            rows.show();
            return;
        }
        rows.hide();
        rows.filter(function(i,v){
            var t = $(this);
            for (var d = 0; d < data.length; d++) {
                if (t.is(":Contains('" + data[d] + "')")) {
                    return true;
                }
            }
            return false;
        }).show();
    });
});

function addNewRow() {
    var table = $('#patientInfo');
    var label = '
' +
        '<input type = "checkbox" id="selectPatient">	' +
        ' {Name}	 ' +
        ' {Hospital Number}	 ' +
        ' {Date of birth}	' +
        '	' +
        '
';

    var dataAppend = label;

    $('div [class = "fillData"] input:text').each(function () {
        switch (this.id) {
            case 'patientName':
                dataAppend = dataAppend.replace('{Name}', this.value);
                break;
            case 'hospitalNum':
                dataAppend = dataAppend.replace('{Hospital Number}', this.value);
                break;
            case 'DOB':
                dataAppend = dataAppend.replace('{Date of birth}', this.value);
                break;
        }
    })

    table.append(dataAppend);
}

<commit_msg>removed addNewPatient method from the javascript file<commit_after>/**
 * Created by Navi on 19/02/2015.
 */

$(function() {
    $( "#DOB" ).datepicker();
});

$(document).ready(function() {
    $("#deletePatients").click(function () {
        $("table input[type ='checkbox']:checked").parent().parent().remove();

    });

    $('#searchPatient').keyup(function () {
        var data = this.value.split(" ");
        var rows = $("#patientInfo tbody tr").hide();
        if(this.value ==""){
            rows.show();
            return;
        }
        rows.hide();
        rows.filter(function(i,v){
            var t = $(this);
            for (var d = 0; d < data.length; d++) {
                if (t.is(":Contains('" + data[d] + "')")) {
                    return true;
                }
            }
            return false;
        }).show();
    });
});

function addNewRow() {
    var table = $('#patientInfo');
    var label = '
' +
        '<input type = "checkbox" id="selectPatient">	' +
        ' {Name}	 ' +
        ' {Hospital Number}	 ' +
        ' {Date of birth}	' +
        '	' +
        '
';

    var dataAppend = label;

    $('div [class = "fillData"] input:text').each(function () {
        switch (this.id) {
            case 'patientName':
                dataAppend = dataAppend.replace('{Name}', this.value);
                break;
            case 'hospitalNum':
                dataAppend = dataAppend.replace('{Hospital Number}', this.value);
                break;
            case 'DOB':
                dataAppend = dataAppend.replace('{Date of birth}', this.value);
                break;
        }
    })

    table.append(dataAppend);
}

<|endoftext|>


<commit_before>'use strict';
let StepNC = require('STEPNode');
let ms = {};
onmessage = (f)=>{
  f=f.data;
  if(f.msg==='setMachineState') {
    ms = new StepNC.machineState(f.path, f.sim);
    if (f.hasOwnProperty('tool'))
      ms.LoadMachine(f.tool);
  } else if(f.msg==='getMachine') {
    let out;
    if(!f.hasOwnProperty('args') || Object.keys(f.args).length <0) {
      out = ms[f.fun]();
    } else {
      if(!f.args.hasOwnProperty('length')){
        f.args.length = Object.keys(f.args).length;
      }
      //Node Native Module calls need to invoke apply with the relevant object.
      //This next line is hairy, but it basically invokes the function our caller wants with the arguments array we have
      if(f.fun==='AdvanceState') {
        ms.AdvanceState().then((r)=>{postMessage({'cb':f.callback,'val':r});});
        return;
      }
      else
        out = ms[f.fun].apply(ms,Array.prototype.slice.call(f.args));
    }
    postMessage({'cb':f.callback,'val':out});
  }
};
<commit_msg>Made machinestate thread more consistent with its promises.<commit_after>'use strict';
let StepNC = require('STEPNode');
let ms = {};
onmessage = (f)=>{
  f=f.data;
  if(f.msg==='setMachineState') {
    ms = new StepNC.machineState(f.path, f.sim);
    if (f.hasOwnProperty('tool'))
      ms.LoadMachine(f.tool);
  } else if(f.msg==='getMachine') {
    let out;
    if(!f.hasOwnProperty('args') || Object.keys(f.args).length <0) {
        Promise.resolve(ms[f.fun]()).then((r)=> {
          postMessage({'cb': f.callback, 'val': r});
        });
        return;
    } else {
      if(!f.args.hasOwnProperty('length')){
        f.args.length = Object.keys(f.args).length;
      }
      //Node Native Module calls need to invoke apply with the relevant object.
      //This next line is hairy, but it basically invokes the function our caller wants with the arguments array we have
        Promise.resolve(ms[f.fun].apply(ms,Array.prototype.slice.call(f.args)))
          .then((r)=>{
            postMessage({'cb': f.callback, 'val': r});
          });
    }
  }
};
<|endoftext|>


<commit_before>/**
 * Worker that monitors health metrics and saves results
 **/
const config = require('../config');
const redis = require('../store/redis');
const db = require('../store/db');
const cassandra = require('../store/cassandra');
const utility = require('../util/utility');
const request = require('request');

const apiKey = config.STEAM_API_KEY.split(',')[0];

function invokeInterval(func) {
  // invokes the function immediately, waits for callback, waits the delay, and then calls it again
  (function invoker() {
    console.log('running %s', func.name);
    console.time(func.name);
    func((err, result) => {
      if (err) {
        console.error(err);
      }
      const final = result || {
        metric: 1,
        threshold: 0,
      };
      final.timestamp = Math.floor(new Date() / 1000);
      redis.hset('health', func.name, JSON.stringify(final));
      redis.expire('health', 900);
      console.timeEnd(func.name);
      setTimeout(invoker, final && final.delay ? final.delay : 10000);
    });
  }());
}

function steamApi(cb) {
  request(`${'http://api.steampowered.com/IDOTA2Match_570/GetMatchHistory/V001/?key='}${apiKey}`, (err, resp, body) => {
    if (err || resp.statusCode !== 200) {
      return cb('bad http response');
    }
    try {
      const fail = err || resp.statusCode !== 200 || JSON.parse(body).result.status !== 1;
      return cb(fail, {
        metric: Number(fail),
        threshold: 1,
      });
    } catch (e) {
      return cb('malformed http response');
    }
  });
}

function seqNumDelay(cb) {
  utility.getData(utility.generateJob('api_history', {}).url, (err, body) => {
    if (err) {
      return cb('failed to get current sequence number');
    }
    // get match_seq_num, compare with real seqnum
    const currSeqNum = body.result.matches[0].match_seq_num;
    return redis.get('match_seq_num', (err, num) => {
      if (err) {
        return cb(err);
      }
      num = Number(num);
      const metric = currSeqNum - num;
      return cb(err, {
        metric,
        threshold: 10000,
      });
    });
  });
}

function postgresUsage(cb) {
  db.raw('select pg_database_size(\'yasp\')').asCallback((err, result) => {
    if (err) {
      return cb(err);
    }
    return cb(err, {
      metric: result.rows[0].pg_database_size,
      threshold: 2 * Math.pow(10, 11),
    });
  });
}

function cassandraUsage(cb) {
  cassandra.execute('select mean_partition_size, partitions_count from system.size_estimates where keyspace_name = \'yasp\'', (err, result) => {
    if (err) {
      return cb(err);
    }
    let size = 0;
    result.rows.forEach((r) => {
      size += r.mean_partition_size * r.partitions_count * 0.5 * 4;
    });
    return cb(err, {
      metric: size,
      threshold: 8 * Math.pow(10, 12),
    });
  });
}

function redisUsage(cb) {
  redis.info((err) => {
    if (err) {
      return cb(err);
    }
    // console.log(info);
    return cb(err, {
      metric: redis.server_info.used_memory,
      threshold: 13 * Math.pow(10, 9),
    });
  });
}
const health = {
  steamApi,
  seqNumDelay,
  postgresUsage,
  cassandraUsage,
  redisUsage,
};
Object.keys(health).forEach((key) => {
  invokeInterval(health[key]);
});
<commit_msg>add health check for parse delay<commit_after>/**
 * Worker that monitors health metrics and saves results
 **/
const config = require('../config');
const redis = require('../store/redis');
const db = require('../store/db');
const cassandra = require('../store/cassandra');
const utility = require('../util/utility');
const request = require('request');
const queue = require('../store/queue');

const apiKey = config.STEAM_API_KEY.split(',')[0];

function invokeInterval(func) {
  // invokes the function immediately, waits for callback, waits the delay, and then calls it again
  (function invoker() {
    console.log('running %s', func.name);
    console.time(func.name);
    func((err, result) => {
      if (err) {
        console.error(err);
      }
      const final = result || {
        metric: 1,
        threshold: 0,
      };
      final.timestamp = Math.floor(new Date() / 1000);
      redis.hset('health', func.name, JSON.stringify(final));
      redis.expire('health', 900);
      console.timeEnd(func.name);
      setTimeout(invoker, final && final.delay ? final.delay : 10000);
    });
  }());
}

function steamApi(cb) {
  request(`${'http://api.steampowered.com/IDOTA2Match_570/GetMatchHistory/V001/?key='}${apiKey}`, (err, resp, body) => {
    if (err || resp.statusCode !== 200) {
      return cb('bad http response');
    }
    try {
      const fail = err || resp.statusCode !== 200 || JSON.parse(body).result.status !== 1;
      return cb(fail, {
        metric: Number(fail),
        threshold: 1,
      });
    } catch (e) {
      return cb('malformed http response');
    }
  });
}

function seqNumDelay(cb) {
  utility.getData(utility.generateJob('api_history', {}).url, (err, body) => {
    if (err) {
      return cb('failed to get current sequence number');
    }
    // get match_seq_num, compare with real seqnum
    const currSeqNum = body.result.matches[0].match_seq_num;
    return redis.get('match_seq_num', (err, num) => {
      if (err) {
        return cb(err);
      }
      num = Number(num);
      const metric = currSeqNum - num;
      return cb(err, {
        metric,
        threshold: 10000,
      });
    });
  });
}

function parseDelay(cb) {
  queue.getCounts(redis, (err, counts) => {
    if (err) {
      return cb(err);
    }
    return cb(err, {
      metric: counts.parse.wait,
      threshold: 1000,
    });
  });
}

function postgresUsage(cb) {
  db.raw('select pg_database_size(\'yasp\')').asCallback((err, result) => {
    if (err) {
      return cb(err);
    }
    return cb(err, {
      metric: result.rows[0].pg_database_size,
      threshold: 2 * Math.pow(10, 11),
    });
  });
}

function cassandraUsage(cb) {
  cassandra.execute('select mean_partition_size, partitions_count from system.size_estimates where keyspace_name = \'yasp\'', (err, result) => {
    if (err) {
      return cb(err);
    }
    let size = 0;
    result.rows.forEach((r) => {
      size += r.mean_partition_size * r.partitions_count * 0.5 * 4;
    });
    return cb(err, {
      metric: size,
      threshold: 8 * Math.pow(10, 12),
    });
  });
}

function redisUsage(cb) {
  redis.info((err) => {
    if (err) {
      return cb(err);
    }
    // console.log(info);
    return cb(err, {
      metric: redis.server_info.used_memory,
      threshold: 13 * Math.pow(10, 9),
    });
  });
}
const health = {
  steamApi,
  seqNumDelay,
  parseDelay,
  postgresUsage,
  cassandraUsage,
  redisUsage,
};
Object.keys(health).forEach((key) => {
  invokeInterval(health[key]);
});
<|endoftext|>


<commit_before>/**
 @adapter DOM Selector, providing basic functionalities of Selector Engine

 allowed methods: (currently)

 1. S.find(selector, context = document, first)
 finds a set of matching elements, always return an array

 always return {Array.<DOMElement>} !important !!!!!!!!!!!!!!

 2. S.contains(context, selector)
 returns {boolean}

 3. S.match(element, selector)
 returns {boolean}

 4. S.uid(element)
 returns {number} the uid of the element

 // TEMP!
 5. S.parse(selector)
 returns {Object} selector object

 arguments:
     context {DOMElement|DOMDocument|Array.<DOMElement>}
     first {boolean} only get the first match of the selector
     selector {string}
     element {DOMElement|DOMDocument}

 within the Neuron Framework, using methods of KM.S besides the above is forbidden

 */

;(function(K){

// Store Slick in closure
var

atom = K._,

Slick = K.Slick;

// adapter for Slick
K.S = {
    find: function(selector, context, append, first){
        context || (context = document);

        if(context._ !== atom){
            context = K.makeArray(context);
        }

        // TODO:
        // selector support Neuron DOM Objects

        // if `selector` is an instance of KM.DOM
        // if(selector._ === atom){
        //    selector = selector.get(0);
        // }

        append || (append = []);

        var context_length = context.length,
            i = 0,
            found,
            c,
            slick = Slick;

        for(; i < context_length; i ++){
            c = context[i];

            // if only get first matched element
            if(first){
                found = slick.find(c, selector);

                // if found stop searching
                if(found){
                    append[0] = found;
                    break;
                }
            }else{
                found = slick.search(c, selector);
                K._pushUnique(found, append);
            }
        }

        // always return an array
        return append;
    },

    contains    : Slick.contains,
    match       : Slick.match,
    parse       : Slick.parse,
    uid         : Slick.uidOf
};

})(KM);

/**

// adapter for Sizzle

*/<commit_msg>adapter: if selector parameter is not true, will return empty result<commit_after>/**
 @adapter DOM Selector, providing basic functionalities of Selector Engine

 allowed methods: (currently)

 1. S.find(selector, context = document, first)
 finds a set of matching elements, always return an array

 always return {Array.<DOMElement>} !important !!!!!!!!!!!!!!

 2. S.contains(context, selector)
 returns {boolean}

 3. S.match(element, selector)
 returns {boolean}

 4. S.uid(element)
 returns {number} the uid of the element

 // TEMP!
 5. S.parse(selector)
 returns {Object} selector object

 arguments:
     context {DOMElement|DOMDocument|Array.<DOMElement>}
     first {boolean} only get the first match of the selector
     selector {string}
     element {DOMElement|DOMDocument}

 within the Neuron Framework, using methods of KM.S besides the above is forbidden

 */

;(function(K){

// Store Slick in closure
var

atom = K._,

Slick = K.Slick;

// adapter for Slick
K.S = {
    find: function(selector, context, append, first){
        context || (context = document);

        if(context._ !== atom){
            context = K.makeArray(context);
        }

        // TODO:
        // selector support Neuron DOM Objects

        // if `selector` is an instance of KM.DOM
        // if(selector._ === atom){
        //    selector = selector.get(0);
        // }

        append || (append = []);

        if(selector){
            var context_length = context.length,
                i = 0,
                found,
                c,
                slick = Slick;

            for(; i < context_length; i ++){
                c = context[i];

                // if only get first matched element
                if(first){
                    found = slick.find(c, selector);

                    // if found stop searching
                    if(found){
                        append[0] = found;
                        break;
                    }
                }else{
                    found = slick.search(c, selector);
                    K._pushUnique(found, append);
                }
            }
        }

        // always return an array
        return append;
    },

    contains    : Slick.contains,
    match       : Slick.match,
    parse       : Slick.parse,
    uid         : Slick.uidOf
};

})(KM);

/**

// adapter for Sizzle

*/<|endoftext|>


<commit_before>BoxParser.sbgpBox.prototype.parse = function(stream) {
	this.parseFullHeader(stream);
	this.grouping_type = stream.readString(4);
	if (this.version === 1) {
		this.grouping_type_parameter = stream.readUint32();
	}
	this.entries = [];
	var entry_count = stream.readUint32();
	for (var i = 0; i < entry_count; i++) {
		var entry = {};
		this.entries.push(entry);
		entry.sample_count = stream.readInt32();
		entry.group_description_index = stream.readInt32();
	}
}

<commit_msg>add default value for grouping type parameter in sbgp parsing<commit_after>BoxParser.sbgpBox.prototype.parse = function(stream) {
	this.parseFullHeader(stream);
	this.grouping_type = stream.readString(4);
	if (this.version === 1) {
		this.grouping_type_parameter = stream.readUint32();
	} else {
		this.grouping_type_parameter = 0;
	}
	this.entries = [];
	var entry_count = stream.readUint32();
	for (var i = 0; i < entry_count; i++) {
		var entry = {};
		this.entries.push(entry);
		entry.sample_count = stream.readInt32();
		entry.group_description_index = stream.readInt32();
	}
}

<|endoftext|>


<commit_before>/*!
Cloud4all Preferences Management Tools

Copyright 2013 CERTH/HIT

Licensed under the New BSD license. You may not use this file except in
compliance with this License.

You may obtain a copy of the License at
https://github.com/GPII/prefsEditors/LICENSE.txt
*/

/*global fluid, jQuery, gpii*/
/*jslint white: true, onevar: true, funcinvoke: true, forvar: true, undef: true, newcap: true, nomen: true, regexp: true, plusplus: true, bitwise: true, maxerr: 50, indent: 4 */

(function ($, fluid) {

    fluid.defaults("gpii.enactor.contrastTheme", {
        gradeNames: ["fluid.prefs.enactor.classSwapper", "autoInit"],
        preferenceMap: {
            "gpii.primarySchema.contrastEnabled": {
                "model.enabled": "default"
            },
            "gpii.primarySchema.contrast.theme": {
                "model.value": "default"
            }
        },
        classes: {
            "bw": "fl-theme-prefsEditor-bw gpii-prefsEditor-theme-bw fl-theme-bw",
            "yb": "fl-theme-prefsEditor-yb gpii-prefsEditor-theme-yb fl-theme-yb",
            "by": "fl-theme-prefsEditor-by gpii-prefsEditor-theme-by fl-theme-by",
            "wb": "fl-theme-prefsEditor-wb gpii-prefsEditor-theme-wb fl-theme-wb"
        }
    });

    // override the swap function
    fluid.prefs.enactor.classSwapper.swap = function (value, that) {
        that.clearClasses();
        if (that.model.enabled) {
            that.container.addClass(that.options.classes[value]);
        }
    };
})(jQuery, fluid);
<commit_msg>GPII-364: Do not override "fluid.prefs.enactor.classSwapper.swap" globally. Create a new swap function and override the invoker.<commit_after>/*!
Cloud4all Preferences Management Tools

Copyright 2013 CERTH/HIT

Licensed under the New BSD license. You may not use this file except in
compliance with this License.

You may obtain a copy of the License at
https://github.com/GPII/prefsEditors/LICENSE.txt
*/

/*global fluid, jQuery, gpii*/
/*jslint white: true, onevar: true, funcinvoke: true, forvar: true, undef: true, newcap: true, nomen: true, regexp: true, plusplus: true, bitwise: true, maxerr: 50, indent: 4 */

(function ($, fluid) {

    fluid.defaults("gpii.enactor.contrastTheme", {
        gradeNames: ["fluid.prefs.enactor.classSwapper", "autoInit"],
        preferenceMap: {
            "gpii.primarySchema.contrastEnabled": {
                "model.enabled": "default"
            },
            "gpii.primarySchema.contrast.theme": {
                "model.value": "default"
            }
        },
        invokers: {
            swap: {
                funcName: "gpii.enactor.contrastTheme.swap",
                args: ["{arguments}.0", "{that}"]
            }
        },
        classes: {
            "bw": "fl-theme-prefsEditor-bw gpii-prefsEditor-theme-bw fl-theme-bw",
            "yb": "fl-theme-prefsEditor-yb gpii-prefsEditor-theme-yb fl-theme-yb",
            "by": "fl-theme-prefsEditor-by gpii-prefsEditor-theme-by fl-theme-by",
            "wb": "fl-theme-prefsEditor-wb gpii-prefsEditor-theme-wb fl-theme-wb"
        }
    });

    gpii.enactor.contrastTheme.swap = function (value, that) {
        that.clearClasses();
        if (that.model.enabled) {
            that.container.addClass(that.options.classes[value]);
        }
    };
})(jQuery, fluid);
<|endoftext|>