<commit_before>var TreeObservable = require("FuseJS/TreeObservable")

require("3rdparty/zone.min")
require("FuseJS/Internal/ZonePatches");

var rootZone = Zone.current;

function shouldEmitProperty(key) {
	return !key.startsWith("__fuse_");
}

function isThenable(thing) {
	return thing instanceof Object
		&& typeof thing.then === "function";
}

function Model(initialState, stateInitializer)
{
	var stateToMeta = new Map();
	var idToMeta = new Map();
	var evaluatingDerivedProps = 0;
	var idEnumerator = 0;
	var store = this;

	instrument(null, this, initialState, stateInitializer)

	function instrument(parentMeta, node, state, stateInitializer)
	{
		if (stateInitializer instanceof Function) {
			runInZone(stateInitializer);
		}

		var meta = stateToMeta.get(state);

		if (meta instanceof Object) {
			if (parentMeta !== null) { meta.parents.push(parentMeta); }
			return meta.node;
		}

		meta = {
			parents: [parentMeta],
			id: idEnumerator++,
			node: node,
			state: state,
			promises: {},
			isClass: false
		}

		idToMeta.set(meta.id, meta);
		stateToMeta.set(state, meta);
		node.__fuse_id = meta.id;
		node.__fuse_raw = state;

		//this is an internal variable but needs to be emitted for use in Uno, the primary use-case is for
		//the default $path for Navigation. Ideally this wouldn't be part of the IObject keys, but it works for now.
		if (state instanceof Object && !('$__fuse_classname' in state)) {
			node.$__fuse_classname = state.constructor.name;
		}

		// create zone lazily to avoid overhead when not needed
		var nodeZone = undefined;
		function prepareZone() {
			if (nodeZone != undefined) { return; }
			nodeZone = rootZone.fork({
				name: (parentMeta != null ? parentMeta.key : '(root)'),
				onInvokeTask: function(parentZoneDelegate, currentZone, targetZone, task, applyThis, applyArgs) {
					dirty();
					parentZoneDelegate.invokeTask(targetZone, task, applyThis, applyArgs);
				},
				onHandleError: function(error) {
					throw error;
				}
			})
		}

		meta.isClass = false;
		for (var k in state) {
			if (!shouldEmitProperty(k)) continue;
			var v = state[k];
			if (v instanceof Function) {
				node[k] = wrapFunction(v);
				state[k] = node[k];
				meta.isClass = true;
			}
			else if (isThenable(v)) {
				node[k] = null;
				dealWithPromise(k, v);
			}
			else if (v instanceof Array) {
				node[k] = instrument({meta: meta, key: k}, [], v);
			}
			else if (v instanceof Object) {
				node[k] = instrument({meta: meta, key: k}, {}, v);
			}
			else
			{
				node[k] = v;
			}
		}

		var propGetters = {}

		if (!(state instanceof Array)) {
			registerProps(state);
		}

		function dealWithPromise(key, prom) {
			if (meta.promises[key] !== prom) {
				meta.promises[key] = prom;
				prom.then(function(result) {
					if (meta.promises[key] === prom) {
						removeAsParentFrom(node[key])
						set(key, wrap(key, result));
					}
				})
			}
		}

		function registerProps(obj) {

			var keys = Object.getOwnPropertyNames(obj);
			for (var i in keys) {
				var p = keys[i];
				if (p === "constructor") { continue; }
				try {
					var value = state[p];
				}
				catch(e) {
					continue;
				}

				if (value instanceof Function) {
					node[p] = wrapFunction(value);
					state[p] = node[p];
				}
				else {
					var descriptor = Object.getOwnPropertyDescriptor(obj, p);
					if (descriptor.get instanceof Function)
					{
						if (isThenable(value)) { node[p] = null; dealWithPromise(p, value); }
						else { node[p] = wrap(p, value); }
						propGetters[p] = descriptor.get;
					}
				}
			}

			// Include members from object's prototype chain (to allow ES6 classes)
			var proto = Object.getPrototypeOf(obj);
			if (proto && proto !== Object.prototype) { registerProps(proto); }
		}

		function hasParent() {
			return meta.parents.length > 0;
		}

		meta.evaluateDerivedProps = function(visited)
		{
			if (!hasParent()) return;

			isDerivedPropsDirty = false;

			if (visited.indexOf(node) !== -1) { return; }
			visited.push(node);

			for (var p in propGetters) {
				evaluatingDerivedProps++;
				try
				{
					var v = propGetters[p].call(state);
					if (isThenable(v)) {
						dealWithPromise(p, v);
					}
					else {
						set(p, wrap(p, v), true); // don't count this as a state change
					}
				}
				finally
				{
					evaluatingDerivedProps--;
				}
			}

			for (var parent of meta.parents) {
				if (parent !== null) {
					parent.meta.evaluateDerivedProps(visited);
				}
			}
		}

		function runInZone(func) {
			prepareZone();
			return nodeZone.run(func);
		}

		function wrapFunction(func) {
			var f = function() {
				var args = arguments;
				return runInZone(function() {
					dirty();
					return func.apply(state, args);
				});
			}
			f.__fuse_isWrapped = true;
			return f;
		}

		var isDirty = false;

		function dirty() {
			if (evaluatingDerivedProps !== 0) { return; }
			if (isDirty) { return; }
			isDirty = true;
			rootZone.run(function() {
				setTimeout(function() {
					meta.diff(new Set())
				}, 0)
			});
		}

		var changesDetected = 0;

		meta.diff = function(visited) {
			if (!(visited instanceof Set)) {
				throw new Error("Needs set of visited nodes");
			}
			if (visited.has(state)) {
				return;
			}
			visited.add(state);

			isDirty = false;

			if (!hasParent()) {
				// This object is no longer attached to the model tree,
				// we got this callback as an async remnant
				return;
			}

			if (state instanceof Array) {
				for (var i = 0; i < Math.min(state.length, node.length); i++) {
					if (isThenable(state[i])) { dealWithPromise(i, state[i]); }
					if (oldValueEquals(i, state[i])) continue;

					if (state.length > node.length) {
						insertAt(i, state[i]);
						i++;
					}
					else if (state.length < node.length) {
						removeRange(i, 1)
						i--;
					}
					else {
						removeAsParentFrom(node[i]);
						set(i, wrap(i, state[i]))
					}
				}

				if (state.length > node.length) {
					addRange(state.slice(node.length, state.length))
				}
				else if (state.length < node.length) {
					removeRange(i, node.length-state.length)
				}
			}
			else {
				for (var k in state) {
					if (!shouldEmitProperty(k)) continue;
					var v = state[k];
					update(k, v, visited);
				}
			}

			if (changesDetected > 0) {
				dirtyDerivedProps()
				changesDetected = 0
			}
		}

		var isDerivedPropsDirty = false;
		function dirtyDerivedProps() {
			if (isDerivedPropsDirty) { return; }
			isDerivedPropsDirty = true;
			rootZone.run(function() {
				setTimeout(function() { meta.evaluateDerivedProps([]) }, 0)
			});
		}

		function oldValueEquals(key, newValue) {
			if (newValue instanceof Object) {
				var keyMeta = stateToMeta.get(newValue);
				return keyMeta instanceof Object && meta.node[key].__fuse_id === keyMeta.id;
			}
			else {
				return node[key] === newValue;
			}
		}

		function removeAsParentFrom(node) {
			if (!(node instanceof Object)) { return; }
			var oldMeta = idToMeta.get(node.__fuse_id);
			if (oldMeta instanceof Object) {
				var thisIndex = oldMeta.parents.findIndex(function(x) { return x.meta == meta });
				oldMeta.parents.splice(thisIndex, 1);
				oldMeta.invalidatePath();

				if (oldMeta.parents.length === 0) {
					idToMeta.delete(node.__fuse_id);
					stateToMeta.delete(oldMeta.state);
				}
			}
		}

		if (node instanceof Array) {
			node.__fuse_replaceAll = function(values) {
				replaceAllInternal(state, values);
				replaceAllInternal(node, values);
				dirty();
			}
		}

		function replaceAllInternal(subject, values) {
			Array.prototype.splice.call(subject, 0);
			Array.prototype.push.apply(subject, values);
		}

		node.__fuse_requestChange = function(key, value) {
			var changeAccepted = true;
			if ('$requestChange' in state) {
				changeAccepted = state.$requestChange(key, value);
			}

			if (changeAccepted) {
				state[key] = value;
				setInternal(meta.getPath(), key, value);
			}

			meta.diff(new Set());
		}

		function update(key, value, visited)
		{
			if (value instanceof Function) {
				if (!value.__fuse_isWrapped) {
					state[key] = wrapFunction(value)
					set(key, state[key]);
				}
			}
			else if (isThenable(value)) {
				dealWithPromise(key, value);
			}
			else if (value instanceof Object) {
				var keyMeta = stateToMeta.get(value);
				var oldValue = meta.node[key];

				var newValue;
				if (keyMeta instanceof Object) {
					// Value is already instrumented
					newValue = keyMeta.node;
				}
				else if (value instanceof Object) {
					newValue = instrument({meta: meta, key: key}, (value instanceof Array) ? [] : {}, value);
				}
				else {
					newValue = value;
				}

				if (oldValue instanceof Object &&
					keyMeta instanceof Object &&
					oldValue.__fuse_id === keyMeta.id
				)
				{
					if (!keyMeta.isClass) {
						keyMeta.diff(visited);
					}
				}
				else {
					removeAsParentFrom(oldValue);
					set(key, newValue);
				}
			}
			else if (value !== node[key])
			{
				set(key, value);
			}
		}

		var cachedPath = null;
		function getPath() {
			if (cachedPath === null) { cachedPath = computePath(); }
			return cachedPath;
		}

		meta.getPath = getPath;
		meta.invalidatePath = function() { cachedPath = null; }

		// Finds a valid path to the root TreeObservable, if any
		function computePath()
		{
			for (var i = 0; i < meta.parents.length; i++) {
				if (meta.parents[i] === null) { return [] }
				else
				{
					var arr = meta.parents[i].meta.getPath();
					if (arr instanceof Array) {
						return arr.concat(meta.parents[i].key);
					}
				}
			}
		}

		function set(key, value, omitStateChange)
		{
			var path = getPath();
			if (!setInternal(path, key, value, omitStateChange)) { return; }

			var argPath = path.concat(key, value instanceof Array ? [value] : value);
			TreeObservable.set.apply(store, argPath);
		}

		function removeRange(index, count) {
			for (var i = 0; i < count; i++) {
				removeAsParentFrom(node[index+i]);
			}
			node.splice(index, count);
			var removePath = getPath().concat(index);
			for (var i = 0; i < count; i++) {
				TreeObservable.removeAt.apply(store, removePath);
			}
			changesDetected++;
		}

		function wrap(key, item) {
			if (isThenable(item)) {
				dealWithPromise(key, item);
			}
			else if (item instanceof Array) {
				return instrument({meta: meta, key: key}, [], item)
			}
			else if (item instanceof Object) {
				return instrument({meta: meta, key: key}, {}, item)
			}
			else {
				return item
			}
		}

		function insertAt(index, item) {
			node.splice(index, 0, null);
			node[index] = item = wrap(index, item)

			TreeObservable.insertAt.apply(store, getPath().concat(index, item));
			changesDetected++;
		}

		function addRange(items) {
			for (var item of items) {
				var index = node.length;
				node.push(null);
				node[index] = item = wrap(index, item);
				TreeObservable.add.apply(store, getPath().concat(item));
			}

			changesDetected++;
		}

		function pathString(key) {
			var path = getPath();
			if (path.length === 0) { return key }
			if (path.length === 1) { return path[0] + "." + key; }
			return path.concat(key).join(".");
		}

		function setInternal(path, key, value, omitStateChange) {
			if (node[key] === value) { return false; }
			node[key] = value;

			if (!omitStateChange) { changesDetected++; }

			return true;
		}

		return node;
	}
}

Model.prototype = Object.create(TreeObservable.prototype);

module.exports = Model;
<commit_msg>Fuse.Scripting.JavaScript: make Model.js require Polyfills/Window<commit_after>var TreeObservable = require("FuseJS/TreeObservable")

require("Polyfills/Window");
require("3rdparty/zone.min")
require("FuseJS/Internal/ZonePatches");

var rootZone = Zone.current;

function shouldEmitProperty(key) {
	return !key.startsWith("__fuse_");
}

function isThenable(thing) {
	return thing instanceof Object
		&& typeof thing.then === "function";
}

function Model(initialState, stateInitializer)
{
	var stateToMeta = new Map();
	var idToMeta = new Map();
	var evaluatingDerivedProps = 0;
	var idEnumerator = 0;
	var store = this;

	instrument(null, this, initialState, stateInitializer)

	function instrument(parentMeta, node, state, stateInitializer)
	{
		if (stateInitializer instanceof Function) {
			runInZone(stateInitializer);
		}

		var meta = stateToMeta.get(state);

		if (meta instanceof Object) {
			if (parentMeta !== null) { meta.parents.push(parentMeta); }
			return meta.node;
		}

		meta = {
			parents: [parentMeta],
			id: idEnumerator++,
			node: node,
			state: state,
			promises: {},
			isClass: false
		}

		idToMeta.set(meta.id, meta);
		stateToMeta.set(state, meta);
		node.__fuse_id = meta.id;
		node.__fuse_raw = state;

		//this is an internal variable but needs to be emitted for use in Uno, the primary use-case is for
		//the default $path for Navigation. Ideally this wouldn't be part of the IObject keys, but it works for now.
		if (state instanceof Object && !('$__fuse_classname' in state)) {
			node.$__fuse_classname = state.constructor.name;
		}

		// create zone lazily to avoid overhead when not needed
		var nodeZone = undefined;
		function prepareZone() {
			if (nodeZone != undefined) { return; }
			nodeZone = rootZone.fork({
				name: (parentMeta != null ? parentMeta.key : '(root)'),
				onInvokeTask: function(parentZoneDelegate, currentZone, targetZone, task, applyThis, applyArgs) {
					dirty();
					parentZoneDelegate.invokeTask(targetZone, task, applyThis, applyArgs);
				},
				onHandleError: function(error) {
					throw error;
				}
			})
		}

		meta.isClass = false;
		for (var k in state) {
			if (!shouldEmitProperty(k)) continue;
			var v = state[k];
			if (v instanceof Function) {
				node[k] = wrapFunction(v);
				state[k] = node[k];
				meta.isClass = true;
			}
			else if (isThenable(v)) {
				node[k] = null;
				dealWithPromise(k, v);
			}
			else if (v instanceof Array) {
				node[k] = instrument({meta: meta, key: k}, [], v);
			}
			else if (v instanceof Object) {
				node[k] = instrument({meta: meta, key: k}, {}, v);
			}
			else
			{
				node[k] = v;
			}
		}

		var propGetters = {}

		if (!(state instanceof Array)) {
			registerProps(state);
		}

		function dealWithPromise(key, prom) {
			if (meta.promises[key] !== prom) {
				meta.promises[key] = prom;
				prom.then(function(result) {
					if (meta.promises[key] === prom) {
						removeAsParentFrom(node[key])
						set(key, wrap(key, result));
					}
				})
			}
		}

		function registerProps(obj) {

			var keys = Object.getOwnPropertyNames(obj);
			for (var i in keys) {
				var p = keys[i];
				if (p === "constructor") { continue; }
				try {
					var value = state[p];
				}
				catch(e) {
					continue;
				}

				if (value instanceof Function) {
					node[p] = wrapFunction(value);
					state[p] = node[p];
				}
				else {
					var descriptor = Object.getOwnPropertyDescriptor(obj, p);
					if (descriptor.get instanceof Function)
					{
						if (isThenable(value)) { node[p] = null; dealWithPromise(p, value); }
						else { node[p] = wrap(p, value); }
						propGetters[p] = descriptor.get;
					}
				}
			}

			// Include members from object's prototype chain (to allow ES6 classes)
			var proto = Object.getPrototypeOf(obj);
			if (proto && proto !== Object.prototype) { registerProps(proto); }
		}

		function hasParent() {
			return meta.parents.length > 0;
		}

		meta.evaluateDerivedProps = function(visited)
		{
			if (!hasParent()) return;

			isDerivedPropsDirty = false;

			if (visited.indexOf(node) !== -1) { return; }
			visited.push(node);

			for (var p in propGetters) {
				evaluatingDerivedProps++;
				try
				{
					var v = propGetters[p].call(state);
					if (isThenable(v)) {
						dealWithPromise(p, v);
					}
					else {
						set(p, wrap(p, v), true); // don't count this as a state change
					}
				}
				finally
				{
					evaluatingDerivedProps--;
				}
			}

			for (var parent of meta.parents) {
				if (parent !== null) {
					parent.meta.evaluateDerivedProps(visited);
				}
			}
		}

		function runInZone(func) {
			prepareZone();
			return nodeZone.run(func);
		}

		function wrapFunction(func) {
			var f = function() {
				var args = arguments;
				return runInZone(function() {
					dirty();
					return func.apply(state, args);
				});
			}
			f.__fuse_isWrapped = true;
			return f;
		}

		var isDirty = false;

		function dirty() {
			if (evaluatingDerivedProps !== 0) { return; }
			if (isDirty) { return; }
			isDirty = true;
			rootZone.run(function() {
				setTimeout(function() {
					meta.diff(new Set())
				}, 0)
			});
		}

		var changesDetected = 0;

		meta.diff = function(visited) {
			if (!(visited instanceof Set)) {
				throw new Error("Needs set of visited nodes");
			}
			if (visited.has(state)) {
				return;
			}
			visited.add(state);

			isDirty = false;

			if (!hasParent()) {
				// This object is no longer attached to the model tree,
				// we got this callback as an async remnant
				return;
			}

			if (state instanceof Array) {
				for (var i = 0; i < Math.min(state.length, node.length); i++) {
					if (isThenable(state[i])) { dealWithPromise(i, state[i]); }
					if (oldValueEquals(i, state[i])) continue;

					if (state.length > node.length) {
						insertAt(i, state[i]);
						i++;
					}
					else if (state.length < node.length) {
						removeRange(i, 1)
						i--;
					}
					else {
						removeAsParentFrom(node[i]);
						set(i, wrap(i, state[i]))
					}
				}

				if (state.length > node.length) {
					addRange(state.slice(node.length, state.length))
				}
				else if (state.length < node.length) {
					removeRange(i, node.length-state.length)
				}
			}
			else {
				for (var k in state) {
					if (!shouldEmitProperty(k)) continue;
					var v = state[k];
					update(k, v, visited);
				}
			}

			if (changesDetected > 0) {
				dirtyDerivedProps()
				changesDetected = 0
			}
		}

		var isDerivedPropsDirty = false;
		function dirtyDerivedProps() {
			if (isDerivedPropsDirty) { return; }
			isDerivedPropsDirty = true;
			rootZone.run(function() {
				setTimeout(function() { meta.evaluateDerivedProps([]) }, 0)
			});
		}

		function oldValueEquals(key, newValue) {
			if (newValue instanceof Object) {
				var keyMeta = stateToMeta.get(newValue);
				return keyMeta instanceof Object && meta.node[key].__fuse_id === keyMeta.id;
			}
			else {
				return node[key] === newValue;
			}
		}

		function removeAsParentFrom(node) {
			if (!(node instanceof Object)) { return; }
			var oldMeta = idToMeta.get(node.__fuse_id);
			if (oldMeta instanceof Object) {
				var thisIndex = oldMeta.parents.findIndex(function(x) { return x.meta == meta });
				oldMeta.parents.splice(thisIndex, 1);
				oldMeta.invalidatePath();

				if (oldMeta.parents.length === 0) {
					idToMeta.delete(node.__fuse_id);
					stateToMeta.delete(oldMeta.state);
				}
			}
		}

		if (node instanceof Array) {
			node.__fuse_replaceAll = function(values) {
				replaceAllInternal(state, values);
				replaceAllInternal(node, values);
				dirty();
			}
		}

		function replaceAllInternal(subject, values) {
			Array.prototype.splice.call(subject, 0);
			Array.prototype.push.apply(subject, values);
		}

		node.__fuse_requestChange = function(key, value) {
			var changeAccepted = true;
			if ('$requestChange' in state) {
				changeAccepted = state.$requestChange(key, value);
			}

			if (changeAccepted) {
				state[key] = value;
				setInternal(meta.getPath(), key, value);
			}

			meta.diff(new Set());
		}

		function update(key, value, visited)
		{
			if (value instanceof Function) {
				if (!value.__fuse_isWrapped) {
					state[key] = wrapFunction(value)
					set(key, state[key]);
				}
			}
			else if (isThenable(value)) {
				dealWithPromise(key, value);
			}
			else if (value instanceof Object) {
				var keyMeta = stateToMeta.get(value);
				var oldValue = meta.node[key];

				var newValue;
				if (keyMeta instanceof Object) {
					// Value is already instrumented
					newValue = keyMeta.node;
				}
				else if (value instanceof Object) {
					newValue = instrument({meta: meta, key: key}, (value instanceof Array) ? [] : {}, value);
				}
				else {
					newValue = value;
				}

				if (oldValue instanceof Object &&
					keyMeta instanceof Object &&
					oldValue.__fuse_id === keyMeta.id
				)
				{
					if (!keyMeta.isClass) {
						keyMeta.diff(visited);
					}
				}
				else {
					removeAsParentFrom(oldValue);
					set(key, newValue);
				}
			}
			else if (value !== node[key])
			{
				set(key, value);
			}
		}

		var cachedPath = null;
		function getPath() {
			if (cachedPath === null) { cachedPath = computePath(); }
			return cachedPath;
		}

		meta.getPath = getPath;
		meta.invalidatePath = function() { cachedPath = null; }

		// Finds a valid path to the root TreeObservable, if any
		function computePath()
		{
			for (var i = 0; i < meta.parents.length; i++) {
				if (meta.parents[i] === null) { return [] }
				else
				{
					var arr = meta.parents[i].meta.getPath();
					if (arr instanceof Array) {
						return arr.concat(meta.parents[i].key);
					}
				}
			}
		}

		function set(key, value, omitStateChange)
		{
			var path = getPath();
			if (!setInternal(path, key, value, omitStateChange)) { return; }

			var argPath = path.concat(key, value instanceof Array ? [value] : value);
			TreeObservable.set.apply(store, argPath);
		}

		function removeRange(index, count) {
			for (var i = 0; i < count; i++) {
				removeAsParentFrom(node[index+i]);
			}
			node.splice(index, count);
			var removePath = getPath().concat(index);
			for (var i = 0; i < count; i++) {
				TreeObservable.removeAt.apply(store, removePath);
			}
			changesDetected++;
		}

		function wrap(key, item) {
			if (isThenable(item)) {
				dealWithPromise(key, item);
			}
			else if (item instanceof Array) {
				return instrument({meta: meta, key: key}, [], item)
			}
			else if (item instanceof Object) {
				return instrument({meta: meta, key: key}, {}, item)
			}
			else {
				return item
			}
		}

		function insertAt(index, item) {
			node.splice(index, 0, null);
			node[index] = item = wrap(index, item)

			TreeObservable.insertAt.apply(store, getPath().concat(index, item));
			changesDetected++;
		}

		function addRange(items) {
			for (var item of items) {
				var index = node.length;
				node.push(null);
				node[index] = item = wrap(index, item);
				TreeObservable.add.apply(store, getPath().concat(item));
			}

			changesDetected++;
		}

		function pathString(key) {
			var path = getPath();
			if (path.length === 0) { return key }
			if (path.length === 1) { return path[0] + "." + key; }
			return path.concat(key).join(".");
		}

		function setInternal(path, key, value, omitStateChange) {
			if (node[key] === value) { return false; }
			node[key] = value;

			if (!omitStateChange) { changesDetected++; }

			return true;
		}

		return node;
	}
}

Model.prototype = Object.create(TreeObservable.prototype);

module.exports = Model;
<|endoftext|>


<commit_before>const reduxish = require('./lib/reduxish');
const way = require('senseway');

const renderers = [
  require('./channelTitleEditor/render'),
  require('./channelTitles/render'),
  require('./timelineViewer/render')
];

const reducers = [
  require('./channelTitleEditor/reduce'),
  require('./channelTitles/reduce'),
  require('./timelineViewer/reduce')
];

const u = null;

module.exports = () => {
  reduxish({
    defaultModel: {
      timeline: [
        [1, 1, 1, u, u, u, u],
        [u, 1, 1, u, u, u, u],
        [u, 1, 1, u, u, u, u],
        [u, 1, 1, u, u, u, u],
        [0, 1, 0, u, u, u, u],
        [0, 0, 0, u, u, u, u],
      ],
      frames: [
        { title: '2019-06-01' },
        { title: '2019-06-02' },
        { title: '2019-06-03' },
        { title: '2019-06-04' },
        { title: '2019-06-05' },
        { title: '2019-06-06' },
        { title: '2019-06-07' }
      ],
      channels: [ // Dimensions
        {
          title: 'Aamiainen',
          backgroundColor: '#8A1C82'
        },
        {
          title: 'Ulkoilu',
          backgroundColor: '#BF0F73'
        },
        {
          title: 'Sarjan katselu',
          backgroundColor: '#201969'
        },
        {
          title: 'Kasvien kastelu',
          backgroundColor: '#223E85'
        },
        {
          title: 'Kiipeily',
          backgroundColor: '#223E85'
        },
        {
          title: 'Uiminen',
          backgroundColor: '#223E85'
        }
      ],
      channelOnEdit: null
    },
    storageName: 'future-model',
    rootElementId: 'content',
    renderers: renderers,
    reducers: reducers
  })
};
<commit_msg>Shorter dates<commit_after>const reduxish = require('./lib/reduxish');
const way = require('senseway');

const renderers = [
  require('./channelTitleEditor/render'),
  require('./channelTitles/render'),
  require('./timelineViewer/render')
];

const reducers = [
  require('./channelTitleEditor/reduce'),
  require('./channelTitles/reduce'),
  require('./timelineViewer/reduce')
];

const u = null;

module.exports = () => {
  reduxish({
    defaultModel: {
      timeline: [
        [1, 1, 1, u, u, u, u],
        [u, 1, 1, u, u, u, u],
        [u, 1, 1, u, u, u, u],
        [u, 1, 1, u, u, u, u],
        [0, 1, 0, u, u, u, u],
        [0, 0, 0, u, u, u, u],
      ],
      frames: [
        { title: '1.6.' },
        { title: '2.6.' },
        { title: '3.6.' },
        { title: '4.6.' },
        { title: '5.6.' },
        { title: '6.6.' },
        { title: '7.6.' }
      ],
      channels: [ // Dimensions
        {
          title: 'Aamiainen',
          backgroundColor: '#8A1C82'
        },
        {
          title: 'Ulkoilu',
          backgroundColor: '#BF0F73'
        },
        {
          title: 'Sarjan katselu',
          backgroundColor: '#201969'
        },
        {
          title: 'Kasvien kastelu',
          backgroundColor: '#223E85'
        },
        {
          title: 'Kiipeily',
          backgroundColor: '#223E85'
        },
        {
          title: 'Uiminen',
          backgroundColor: '#223E85'
        }
      ],
      channelOnEdit: null
    },
    storageName: 'future-model',
    rootElementId: 'content',
    renderers: renderers,
    reducers: reducers
  })
};
<|endoftext|>


<commit_before><commit_msg>no class to create a game<commit_after>"use strict";
var assert = require('assert');

describe('bowling game', function() {
  it('is able to create a game', function() {
    assert(new Game());
  });
});<|endoftext|>


<commit_before>frappe.tests = {
	data: {},
	get_fixture_names: (doctype) => {
		return Object.keys(frappe.test_data[doctype]);
	},
	make: function(doctype, data) {
		return frappe.run_serially([
			() => frappe.set_route('List', doctype),
			() => frappe.new_doc(doctype),
			() => {
				if (frappe.quick_entry)
				{
					frappe.quick_entry.dialog.$wrapper.find('.edit-full').click();
					return frappe.timeout(1);
				}
			},
			() => {
				return frappe.tests.set_form_values(cur_frm, data);
			},
			() => frappe.timeout(1),
			() => (frappe.quick_entry ? frappe.quick_entry.insert() : cur_frm.save())
		]);
	},
	set_form_values: (frm, data) => {
		let tasks = [];

		data.forEach(item => {
			for (let key in item) {
				let task = () => {
					let value = item[key];
					if ($.isArray(value)) {
						return frappe.tests.set_grid_values(frm, key, value);
					} else {
						// single value
						return frm.set_value(key, value);
					}
				};
				tasks.push(task);
			}
		});

		// set values
		return frappe.run_serially(tasks);

	},
	set_grid_values: (frm, key, value) => {
		// set value in grid
		let grid = frm.get_field(key).grid;
		grid.remove_all();

		let grid_row_tasks = [];

		// build tasks for each row
		value.forEach(d => {
			grid_row_tasks.push(() => {
				grid.add_new_row();
				let grid_row = grid.get_row(-1).toggle_view(true);
				let grid_value_tasks = [];

				// build tasks to set each row value
				d.forEach(child_value => {
					for (let child_key in child_value) {
						grid_value_tasks.push(() => {
							return frappe.model.set_value(grid_row.doc.doctype,
								grid_row.doc.name, child_key, child_value[child_key]);
						});
					}
				});

				return frappe.run_serially(grid_value_tasks);
			});
		});
		return frappe.run_serially(grid_row_tasks);
	},
	setup_doctype: (doctype) => {
		return frappe.run_serially([
			() => frappe.set_route('List', doctype),
			() => frappe.timeout(1),
			() => {
				frappe.tests.data[doctype] = [];
				let expected = frappe.tests.get_fixture_names(doctype);
				cur_list.data.forEach((d) => {
					frappe.tests.data[doctype].push(d.name);
					if(expected.indexOf(d.name) !== -1) {
						expected[expected.indexOf(d.name)] = null;
					}
				});

				let tasks = [];

				expected.forEach(function(d) {
					if(d) {
						tasks.push(() => frappe.tests.make(doctype,
							frappe.test_data[doctype][d]));
					}
				});

				return frappe.run_serially(tasks);
			}]);
	},
	click_and_wait: (button, obj=0.1) => {
		return frappe.run_serially([
			() => {
				//check if obj value is passed
				if (obj == 0.1)
					$(button).click();
				else
					$(button)[obj].click();
			},
			() => frappe.timeout(0.5)
		]);
	},
	create_todo: (todo_needed) => {
		let status_list = ['Closed', 'Open'];
		let priority_list = ['Low', 'Medium', 'High'];
		let date_list = ['2017-05-05', '2017-06-06', '2017-07-07', '2017-08-08'];
		let owner_list = ['Administrator', 'user1@mail.com'];
		let i;
		let num_of_todo;
		let tasks = [];

		return frappe.run_serially([
			() => frappe.set_route('List', 'ToDo', 'List'),
			() => {
				//remove todo filters
				for (i=1; i<=5; i++)
					$('.col-md-2:nth-child('+i+') .input-sm').val('');
			},
			() => cur_list.page.btn_secondary.click(),
			() => frappe.timeout(0.5),
			() => num_of_todo = cur_list.data.length,//todo present
			() => {
				if (num_of_todo < todo_needed)
				{
					for (i=0; i<(todo_needed-num_of_todo); i+=1)
					{
						tasks.push(() => frappe.tests.make("ToDo", [
							{description: 'ToDo for testing'},
							{status: status_list[i%2]},
							{priority: priority_list[i%3]},
							{date: date_list[i%4]},
							{owner: owner_list[i%2]}
						]));
						tasks.push(() => i+=1);
					}
					i=0;
				}
			},
			() => frappe.run_serially(tasks)
		]);
	},
	click_page_head_item: (text) => {
		// Method to items present on the page header like New, Save, Delete etc.
		let  possible_texts = ["New", "Delete", "Save", "Yes"];
		return frappe.run_serially([
			() => {
				if (text == "Menu"){
					$(`span.menu-btn-group-label:contains('Menu'):visible`).click();
				} else if (text == "Refresh") {
					$(`.btn-secondary:contains('Refresh'):visible`).click();
				} else if (possible_texts.includes(text)) {
					$(`.btn-primary:contains("${text}"):visible`).click();
				}
			},
			() => frappe.timeout(1)
		]);
	},
	click_dropdown_item: (text) => {
		// Method to click dropdown elements
		return frappe.run_serially([
			() => {
				let li = $(`.dropdown-menu li:contains("${text}"):visible`).get(0);
				$(li).find(`a`)[0].click();
			},
			() => frappe.timeout(1)
		]);
	},
	click_navbar_item: (text) => {
		// Method to click an elements present on the navbar
		return frappe.run_serially([
			() => {
				if (text == "Help"){
					$(`.dropdown-help .dropdown-toggle:visible`).click();
				}
				else if (text == "navbar_user"){
					$(`.dropdown-navbar-user .dropdown-toggle:visible`).click();
				}
				else if (text == "Notification"){
					$(`.navbar-new-comments`).click();
				}
				else if (text == "Home"){
					$(`.navbar-home:contains('Home'):visible`)[0].click();
				}
			},
			() => frappe.timeout(1)
		]);
	},
	click_generic_text: (text, tag='a') => {
		// Method to click an element by its name
		return frappe.run_serially([
			() => $(`${tag}:contains("${text}"):visible`)[0].click(),
			() => frappe.timeout(1)
		]);
	},
	click_desktop_icon: (text) => {
		// Method to click the desktop icons on the Desk, by their name
		return frappe.run_serially([
			() => $("#icon-grid > div > div.app-icon[title="+text+"]").click(),
			() => frappe.timeout(1)
		]);
	},
	is_visible: (text, tag='a') => {
		// Method to check the visibility of an element
		return $(`${tag}:contains("${text}")`).is(`:visible`);
	},
	close_modal: () => {
		// Close the modal on the screen
		$(`a.close`).click();
	},
	click_print_logo: () => {
		return frappe.run_serially([
			() => $(`.fa-print`).click(),
			() => frappe.timeout(1)
		]);
	},
	click_button: function(text) {
		$(`.btn:contains("${text}"):visible`).click();
		return frappe.timeout(1);
	},
	click_link: function(text) {
		$(`a:contains("${text}"):visible`).click();
		return frappe.timeout(1);
	}
};<commit_msg>[minor] added timeout while setting values<commit_after>frappe.tests = {
	data: {},
	get_fixture_names: (doctype) => {
		return Object.keys(frappe.test_data[doctype]);
	},
	make: function(doctype, data) {
		return frappe.run_serially([
			() => frappe.set_route('List', doctype),
			() => frappe.new_doc(doctype),
			() => {
				if (frappe.quick_entry)
				{
					frappe.quick_entry.dialog.$wrapper.find('.edit-full').click();
					return frappe.timeout(1);
				}
			},
			() => {
				return frappe.tests.set_form_values(cur_frm, data);
			},
			() => frappe.timeout(1),
			() => (frappe.quick_entry ? frappe.quick_entry.insert() : cur_frm.save())
		]);
	},
	set_form_values: (frm, data) => {
		let tasks = [];

		data.forEach(item => {
			for (let key in item) {
				let task = () => {
					let value = item[key];
					if ($.isArray(value)) {
						return frappe.tests.set_grid_values(frm, key, value);
					} else {
						// single value
						return frm.set_value(key, value);
					}
				};
				tasks.push(task);
				tasks.push(() => frappe.timeout(0.2));
			}
		});

		// set values
		return frappe.run_serially(tasks);

	},
	set_grid_values: (frm, key, value) => {
		// set value in grid
		let grid = frm.get_field(key).grid;
		grid.remove_all();

		let grid_row_tasks = [];

		// build tasks for each row
		value.forEach(d => {
			grid_row_tasks.push(() => {
				grid.add_new_row();
				let grid_row = grid.get_row(-1).toggle_view(true);
				let grid_value_tasks = [];

				// build tasks to set each row value
				d.forEach(child_value => {
					for (let child_key in child_value) {
						grid_value_tasks.push(() => {
							return frappe.model.set_value(grid_row.doc.doctype,
								grid_row.doc.name, child_key, child_value[child_key]);
						});
						grid_value_tasks.push(() => frappe.timeout(0.2));
					}
				});

				return frappe.run_serially(grid_value_tasks);
			});
		});
		return frappe.run_serially(grid_row_tasks);
	},
	setup_doctype: (doctype) => {
		return frappe.run_serially([
			() => frappe.set_route('List', doctype),
			() => frappe.timeout(1),
			() => {
				frappe.tests.data[doctype] = [];
				let expected = frappe.tests.get_fixture_names(doctype);
				cur_list.data.forEach((d) => {
					frappe.tests.data[doctype].push(d.name);
					if(expected.indexOf(d.name) !== -1) {
						expected[expected.indexOf(d.name)] = null;
					}
				});

				let tasks = [];

				expected.forEach(function(d) {
					if(d) {
						tasks.push(() => frappe.tests.make(doctype,
							frappe.test_data[doctype][d]));
					}
				});

				return frappe.run_serially(tasks);
			}]);
	},
	click_and_wait: (button, obj=0.1) => {
		return frappe.run_serially([
			() => {
				//check if obj value is passed
				if (obj == 0.1)
					$(button).click();
				else
					$(button)[obj].click();
			},
			() => frappe.timeout(0.5)
		]);
	},
	create_todo: (todo_needed) => {
		let status_list = ['Closed', 'Open'];
		let priority_list = ['Low', 'Medium', 'High'];
		let date_list = ['2017-05-05', '2017-06-06', '2017-07-07', '2017-08-08'];
		let owner_list = ['Administrator', 'user1@mail.com'];
		let i;
		let num_of_todo;
		let tasks = [];

		return frappe.run_serially([
			() => frappe.set_route('List', 'ToDo', 'List'),
			() => {
				//remove todo filters
				for (i=1; i<=5; i++)
					$('.col-md-2:nth-child('+i+') .input-sm').val('');
			},
			() => cur_list.page.btn_secondary.click(),
			() => frappe.timeout(0.5),
			() => num_of_todo = cur_list.data.length,//todo present
			() => {
				if (num_of_todo < todo_needed)
				{
					for (i=0; i<(todo_needed-num_of_todo); i+=1)
					{
						tasks.push(() => frappe.tests.make("ToDo", [
							{description: 'ToDo for testing'},
							{status: status_list[i%2]},
							{priority: priority_list[i%3]},
							{date: date_list[i%4]},
							{owner: owner_list[i%2]}
						]));
						tasks.push(() => i+=1);
					}
					i=0;
				}
			},
			() => frappe.run_serially(tasks)
		]);
	},
	click_page_head_item: (text) => {
		// Method to items present on the page header like New, Save, Delete etc.
		let  possible_texts = ["New", "Delete", "Save", "Yes"];
		return frappe.run_serially([
			() => {
				if (text == "Menu"){
					$(`span.menu-btn-group-label:contains('Menu'):visible`).click();
				} else if (text == "Refresh") {
					$(`.btn-secondary:contains('Refresh'):visible`).click();
				} else if (possible_texts.includes(text)) {
					$(`.btn-primary:contains("${text}"):visible`).click();
				}
			},
			() => frappe.timeout(1)
		]);
	},
	click_dropdown_item: (text) => {
		// Method to click dropdown elements
		return frappe.run_serially([
			() => {
				let li = $(`.dropdown-menu li:contains("${text}"):visible`).get(0);
				$(li).find(`a`)[0].click();
			},
			() => frappe.timeout(1)
		]);
	},
	click_navbar_item: (text) => {
		// Method to click an elements present on the navbar
		return frappe.run_serially([
			() => {
				if (text == "Help"){
					$(`.dropdown-help .dropdown-toggle:visible`).click();
				}
				else if (text == "navbar_user"){
					$(`.dropdown-navbar-user .dropdown-toggle:visible`).click();
				}
				else if (text == "Notification"){
					$(`.navbar-new-comments`).click();
				}
				else if (text == "Home"){
					$(`.navbar-home:contains('Home'):visible`)[0].click();
				}
			},
			() => frappe.timeout(1)
		]);
	},
	click_generic_text: (text, tag='a') => {
		// Method to click an element by its name
		return frappe.run_serially([
			() => $(`${tag}:contains("${text}"):visible`)[0].click(),
			() => frappe.timeout(1)
		]);
	},
	click_desktop_icon: (text) => {
		// Method to click the desktop icons on the Desk, by their name
		return frappe.run_serially([
			() => $("#icon-grid > div > div.app-icon[title="+text+"]").click(),
			() => frappe.timeout(1)
		]);
	},
	is_visible: (text, tag='a') => {
		// Method to check the visibility of an element
		return $(`${tag}:contains("${text}")`).is(`:visible`);
	},
	close_modal: () => {
		// Close the modal on the screen
		$(`a.close`).click();
	},
	click_print_logo: () => {
		return frappe.run_serially([
			() => $(`.fa-print`).click(),
			() => frappe.timeout(1)
		]);
	},
	click_button: function(text) {
		$(`.btn:contains("${text}"):visible`).click();
		return frappe.timeout(1);
	},
	click_link: function(text) {
		$(`a:contains("${text}"):visible`).click();
		return frappe.timeout(1);
	}
};<|endoftext|>


<commit_before>

// MAP DATA REQUEST CALCULATORS //////////////////////////////////////
// Ingress Intel splits up requests for map data (portals, links,
// fields) into tiles. To get data for the current viewport (i.e. what
// is currently visible) it first calculates which tiles intersect.
// For all those tiles, it then calculates the lat/lng bounds of that
// tile and a quadkey. Both the bounds and the quadkey are “somewhat”
// required to get complete data. No idea how the projection between
// lat/lng and tiles works.
// What follows now are functions that allow conversion between tiles
// and lat/lng as well as calculating the quad key. The variable names
// may be misleading.
// The minified source for this code was in gen_dashboard.js after the
// “// input 89” line (alternatively: the class was called “Xe”).

window.convertCenterLat = function(centerLat) {
  return Math.round(256 * 0.9999 * Math.abs(1 / Math.cos(centerLat * DEG2RAD)));
}

window.calculateR = function(convCenterLat) {
  return 1 << window.map.getZoom() - (convCenterLat / 256 - 1);
}

window.convertLatLngToPoint = function(latlng, magic, R) {
  var x = (magic/2 + latlng.lng * magic / 360)*R;
  var l = Math.sin(latlng.lat * DEG2RAD);
  var y =  (magic/2 + 0.5*Math.log((1+l)/(1-l)) * -(magic / (2*Math.PI)))*R;
  return {x: Math.floor(x/magic), y: Math.floor(y/magic)};
}

window.convertPointToLatLng = function(x, y, magic, R) {
  var e = {};
  e.sw = {
    // orig function put together from all over the place
    // lat: (2 * Math.atan(Math.exp((((y + 1) * magic / R) - (magic/ 2)) / (-1*(magic / (2 * Math.PI))))) - Math.PI / 2) / (Math.PI / 180),
    // shortened version by your favorite algebra program.
    lat: (360*Math.atan(Math.exp(Math.PI - 2*Math.PI*(y+1)/R)))/Math.PI - 90,
    lng: 360*x/R-180
  };
  e.ne = {
    //lat: (2 * Math.atan(Math.exp(((y * magic / R) - (magic/ 2)) / (-1*(magic / (2 * Math.PI))))) - Math.PI / 2) / (Math.PI / 180),
    lat: (360*Math.atan(Math.exp(Math.PI - 2*Math.PI*y/R)))/Math.PI - 90,
    lng: 360*(x+1)/R-180
  };
  return e;
}

// calculates the quad key for a given point. The point is not(!) in
// lat/lng format.
window.pointToQuadKey = function(x, y) {
  var quadkey = [];
  for(var c = window.map.getZoom(); c > 0; c--) {
    //  +-------+   quadrants are probably ordered like this
    //  | 0 | 1 |
    //  |---|---|
    //  | 2 | 3 |
    //  |---|---|
    var quadrant = 0;
    var e = 1 << c - 1;
    (x & e) != 0 && quadrant++;               // push right
    (y & e) != 0 && (quadrant++, quadrant++); // push down
    quadkey.push(quadrant);
  }
  return quadkey.join("");
}

// given quadkey and bounds, returns the format as required by the
// Ingress API to request map data.
window.generateBoundsParams = function(quadkey, bounds) {
  return {
    id: quadkey,
    qk: quadkey,
    minLatE6: Math.round(bounds.sw.lat * 1E6),
    minLngE6: Math.round(bounds.sw.lng * 1E6),
    maxLatE6: Math.round(bounds.ne.lat * 1E6),
    maxLngE6: Math.round(bounds.ne.lng * 1E6)
  };
}
<commit_msg>Updated quadkey calculations for new protocol<commit_after>
// MAP DATA REQUEST CALCULATORS //////////////////////////////////////
// Ingress Intel splits up requests for map data (portals, links,
// fields) into tiles. To get data for the current viewport (i.e. what
// is currently visible) it first calculates which tiles intersect.
// For all those tiles, it then calculates the lat/lng bounds of that
// tile and a quadkey. Both the bounds and the quadkey are “somewhat”
// required to get complete data. No idea how the projection between
// lat/lng and tiles works.
// What follows now are functions that allow conversion between tiles
// and lat/lng as well as calculating the quad key. The variable names
// may be misleading.
// The minified source for this code was in gen_dashboard.js after the
// “// input 89” line (alternatively: the class was called “Xe”).

window.convertCenterLat = function(centerLat) {
  return Math.round(256 * 0.9999 * Math.abs(1 / Math.cos(centerLat * DEG2RAD)));
}

window.calculateR = function(convCenterLat) {
  return 1 << window.map.getZoom() - (convCenterLat / 256 - 1);
}

window.convertLatLngToPoint = function(latlng, magic, R) {
  var x = (magic + latlng.lng * magic / 180)*R;
  var l = Math.sin(latlng.lat * DEG2RAD);
  var y =  (magic + Math.log((1+l)/(1-l)) * -(magic / (2*Math.PI)))*R;
  return {x: Math.floor(x/magic), y: Math.floor(y/magic)};
}

window.convertPointToLatLng = function(x, y, magic, R) {
  var e = {};
  e.sw = {
    // orig function put together from all over the place
    // lat: (2 * Math.atan(Math.exp((((y + 1) * magic / R) - (magic/ 2)) / (-1*(magic / (2 * Math.PI))))) - Math.PI / 2) / (Math.PI / 180),
    // shortened version by your favorite algebra program.
    lat: (360*Math.atan(Math.exp(Math.PI - Math.PI*(y+1)/R)))/Math.PI - 90,
    lng: 180*x/R-180
  };
  e.ne = {
    //lat: (2 * Math.atan(Math.exp(((y * magic / R) - (magic/ 2)) / (-1*(magic / (2 * Math.PI))))) - Math.PI / 2) / (Math.PI / 180),
    lat: (360*Math.atan(Math.exp(Math.PI - Math.PI*y/R)))/Math.PI - 90,
    lng: 180*(x+1)/R-180
  };
  return e;
}

// calculates the quad key for a given point. The point is not(!) in
// lat/lng format.
window.pointToQuadKey = function(x, y) {
  return window.map.getZoom() + "_" + x + "_" + y;
  /*var quadkey = [];
  for(var c = window.map.getZoom(); c > 0; c--) {
    //  +-------+   quadrants are probably ordered like this
    //  | 0 | 1 |
    //  |---|---|
    //  | 2 | 3 |
    //  |---|---|
    var quadrant = 0;
    var e = 1 << c - 1;
    (x & e) != 0 && quadrant++;               // push right
    (y & e) != 0 && (quadrant++, quadrant++); // push down
    quadkey.push(quadrant);
  }
  return quadkey.join("");*/
}

// given quadkey and bounds, returns the format as required by the
// Ingress API to request map data.
window.generateBoundsParams = function(quadkey, bounds) {
  return {
    id: quadkey,
    qk: quadkey,
    minLatE6: Math.round(bounds.sw.lat * 1E6),
    minLngE6: Math.round(bounds.sw.lng * 1E6),
    maxLatE6: Math.round(bounds.ne.lat * 1E6),
    maxLngE6: Math.round(bounds.ne.lng * 1E6)
  };
}
<|endoftext|>


<commit_before>/* globals describe, it, expect, expectObservable, hot */
var Rx = require('../../dist/cjs/Rx');
var Observable = Rx.Observable;

describe('Observable.prototype.skip()', function () {
  it('should skip values before a total', function () {
    var source = hot('--a--b--c--d--e--|');
    var expected =   '-----------d--e--|';

    expectObservable(source.skip(3)).toBe(expected);
  });

   it('should skip all values without error if total is more than actual number of values', function () {
    var source = hot('--a--b--c--d--e--|');
    var expected =   '-----------------|';

    expectObservable(source.skip(6)).toBe(expected);
  });
});<commit_msg>test(skip): add marble tests for skip operator<commit_after>/* globals describe, it, expect, expectObservable, hot */
var Rx = require('../../dist/cjs/Rx');
var Observable = Rx.Observable;

describe('Observable.prototype.skip()', function () {
  it('should skip values before a total', function () {
    var source = hot('--a--b--c--d--e--|');
    var expected =   '-----------d--e--|';

    expectObservable(source.skip(3)).toBe(expected);
  });

  it('should skip all values without error if total is more than actual number of values', function () {
    var source = hot('--a--b--c--d--e--|');
    var expected =   '-----------------|';

    expectObservable(source.skip(6)).toBe(expected);
  });

  it('should skip all values without error if total is same as actual number of values', function () {
    var source = hot('--a--b--c--d--e--|');
    var expected =   '-----------------|';

    expectObservable(source.skip(5)).toBe(expected);
  });

  it('should not skip if count is zero', function () {
    var source = hot('--a--b--c--d--e--|');
    var expected =   '--a--b--c--d--e--|';

    expectObservable(source.skip(0)).toBe(expected);
  });

  it('should raise error if skip count is more than actual number of emits and source raises error', function() {
    var source = hot('--a--b--c--d--#');
    var expected =   '--------------#';

    expectObservable(source.skip(6)).toBe(expected);
  });

  it('should raise error if skip count is same as emits of source and source raises error', function() {
    var source = hot('--a--b--c--d--#');
    var expected =   '--------------#';

    expectObservable(source.skip(4)).toBe(expected);
  });

  it('should skip values before a total and raises error if source raises error', function() {
    var source = hot('--a--b--c--d--#');
    var expected =   '-----------d--#';

    expectObservable(source.skip(3)).toBe(expected);
  });

  it('should complete regardless of skip count if source is empty', function() {
    var e1 = Observable.empty();
    var expected = '|';

    expectObservable(e1.skip(3)).toBe(expected);
  });

  it('should not complete if source never completes without emit', function() {
    var e1 = hot('-');
    var expected = '-';

    expectObservable(e1.skip(3)).toBe(expected);
  });

  it('should skip values before total and never completes if source emits and does not complete', function() {
    var e1 =   hot('--a--b--c-');
    var expected = '-----b--c-';

    expectObservable(e1.skip(1)).toBe(expected);
  });

  it('should skip all values and never completes if total is more than numbers of value and source does not complete', function() {
    var e1 =   hot('--a--b--c-');
    var expected = '-';

    expectObservable(e1.skip(6)).toBe(expected);
  });

  it('should skip all values and never completes if total is same asnumbers of value and source does not complete', function() {
    var e1 =   hot('--a--b--c-');
    var expected = '-';

    expectObservable(e1.skip(3)).toBe(expected);
  });

  it('should raise error if source throws', function(){
    var error = 'error';
    var e1 = Observable.throw(error);
    var expected = '#';

    expectObservable(e1.skip(3)).toBe(expected, null, error);
  });
});<|endoftext|>


<commit_before>/**
 * Module Name: Flashy
 * Description: Makes pages with flashing text and that innit.
 */

var _ = require('underscore')._;

var flashy = function(dbot) {
    this.colourMap = {
        'white': 'FFFFFF',
        'red': 'FF0000',
        'green': '00FF00',
        'blue': '0000FF',
        'yellow': 'FFFF00',
        'magenta': 'FF00FF',
        'cyan': '00FFFF'
    };

    this.commands = {
        '~flashy': function(event) {
            var colour = event.input[1].trim();
            var text = event.input[2].trim().toUpperCase();

            if(_.has(this.colourMap, colour)) {
                event.reply(dbot.t('url', {
                    'host': dbot.config.web.webHost,
                    'port': dbot.config.web.webPort,
                    'path': 'flashy/' + colour + '/' + encodeURIComponent(text)
                }));
            } else {
                var possibleColours = _.keys(this.colourMap).join(', ').slice(0, -2) + '.';
                event.reply('No such colour, brah. Available colours are: ' + possibleColours);
            }
        }
    };

    this.commands['~flashy'].regex = [/^~flashy ([\d\w-]+[\d\w\s-]*)[ ]?=[ ]?(.+)$/, 3];
};

exports.fetch = function(dbot) {
    return new flashy(dbot);
};
<commit_msg>no blank at end<commit_after>/**
 * Module Name: Flashy
 * Description: Makes pages with flashing text and that innit.
 */

var _ = require('underscore')._;

var flashy = function(dbot) {
    this.colourMap = {
        'white': 'FFFFFF',
        'red': 'FF0000',
        'green': '00FF00',
        'blue': '0000FF',
        'yellow': 'FFFF00',
        'magenta': 'FF00FF',
        'cyan': '00FFFF'
    };

    this.commands = {
        '~flashy': function(event) {
            var colour = event.input[1].trim();
            var text = event.input[2].trim().toUpperCase();

            if(_.has(this.colourMap, colour)) {
                event.reply(dbot.t('url', {
                    'host': dbot.config.web.webHost,
                    'port': dbot.config.web.webPort,
                    'path': 'flashy/' + colour + '/' + encodeURIComponent(text)
                }));
            } else {
                var possibleColours = _.keys(this.colourMap).join(', ') + '.';
                event.reply('No such colour, brah. Available colours are: ' + possibleColours);
            }
        }
    };

    this.commands['~flashy'].regex = [/^~flashy ([\d\w-]+[\d\w\s-]*)[ ]?=[ ]?(.+)$/, 3];
};

exports.fetch = function(dbot) {
    return new flashy(dbot);
};
<|endoftext|>


<commit_before>/* global sinon */

import React from 'react';

import { mount } from 'enzyme';

import {
  default as BpmnEditorWithCachedState,
  BpmnEditor
} from '../BpmnEditor';

import { SlotFillRoot } from 'src/app/slot-fill';

import diagramXML from './diagram.bpmn';

import { insertCSS } from 'test/helper';

insertCSS('test.css', '.test-content-container { position: relative; }');

describe('<BpmnEditor>', function() {

  let createCachedSpy;

  beforeEach(function() {
    createCachedSpy = sinon.spy(BpmnEditor, 'createCachedState');
  });

  afterEach(function() {
    createCachedSpy.restore();
  });

  it('should render', function() {
    const {
      bpmnEditor
    } = renderBpmnEditor(diagramXML);

    expect(bpmnEditor).to.exist;
  });

  // TODO(philippfromme): spy is not called if test isn't executed exclusively
  it.skip('should create modeler if no cached modeler', function() {

    const {
      bpmnEditor
    } = renderBpmnEditor(diagramXML);

    const {
      modeler
    } = bpmnEditor.getCached();

    expect(createCachedSpy).to.have.been.calledOnce;
    expect(modeler).to.exist;
  });

  it('should use existing modeler if cached modeler');

  it('#getXML', async function() {
    const {
      bpmnEditor
    } = renderBpmnEditor(diagramXML);

    const xml = await bpmnEditor.getXML();

    expect(xml).to.exist;
    expect(xml).to.eql(diagramXML);
  });

  describe('#exportAs', function() {

    let bpmnEditor;

    beforeEach(function() {
      bpmnEditor = renderBpmnEditor(diagramXML).bpmnEditor;
    });

    it('svg', async function() {
      const contents = await bpmnEditor.exportAs('svg');

      expect(contents).to.exist;
      expect(contents).to.equal('<svg />');
    });

    it('png', async function() {
      const contents = await bpmnEditor.exportAs('png');

      expect(contents).to.exist;
      expect(contents).to.contain('data:image/png');
    });

    it('jpeg', async function() {
      const contents = await bpmnEditor.exportAs('jpeg');

      expect(contents).to.exist;
      expect(contents).to.contain('data:image/jpeg');
    });

  });

  describe('layout', function() {

    it('should open properties panel', function() {

      // given
      const {
        bpmnEditor,
        wrapper
      } = renderBpmnEditor(diagramXML, {
        layout: {
          propertiesPanel: {
            open: false
          }
        }
      });

      const toggle = wrapper.find('.toggle');

      // when
      toggle.simulate('click');

      // then
      expect(bpmnEditor.state.layout.propertiesPanel.open).to.be.true;
    });

    it('should close properties panel', function() {

      // given
      const {
        bpmnEditor,
        wrapper
      } = renderBpmnEditor(diagramXML);

      const toggle = wrapper.find('.toggle');

      // when
      toggle.simulate('click');

      // then
      expect(bpmnEditor.state.layout.propertiesPanel.open).to.be.false;
    });

    it('should handle missing layout', function() {

      // when
      const {
        bpmnEditor
      } = renderBpmnEditor(diagramXML, {
        layout: {}
      });

      // then
      expect(bpmnEditor.state.layout).to.eql({
        minimap: {
          open: false
        },
        propertiesPanel: {
          open: true
        }
      });
    });

    it('it should apply received layout', function() {

      // when
      const {
        bpmnEditor
      } = renderBpmnEditor(diagramXML, {
        layout: {
          minimap: {
            open: true
          },
          propertiesPanel: {
            open: false
          }
        }
      });

      // then
      expect(bpmnEditor.state.layout).to.eql({
        minimap: {
          open: true
        },
        propertiesPanel: {
          open: false
        }
      });
    });

  });

  describe('errors', function() {

    // TODO
    it('should handle template error');

    // TODO(philippfromme): why does import not return error?
    it.skip('should handle import error', function() {

      // given
      const onErrorSpy = sinon.spy();

      const errorXML = 'foo';

      // when
      renderBpmnEditor(errorXML, {
        onError: onErrorSpy
      });

      // then
      expect(onErrorSpy).to.have.been.called;
    });

    it('should handle export error', function() {
      // TODO(philippfromme): how to make #getXML throw?
    });

    it('should handle export error', function() {
      // TODO(philippfromme): how to make #exportAs throw?
    });

  });

});

function noop() {}

function renderBpmnEditor(xml, options = {}) {
  const {
    layout,
    onError,
    onLayoutChanged
  } = options;

  const slotFillRoot = mount(
    <SlotFillRoot>
      <BpmnEditorWithCachedState
        id="foo"
        xml={ xml }
        onLayoutChanged={ onLayoutChanged || noop }
        onError={ onError || noop }
        layout={ layout || {
          minimap: {
            open: false
          },
          propertiesPanel: {
            open: true
          }
        } } />
    </SlotFillRoot>
  );

  const wrapper = slotFillRoot.find(BpmnEditor);

  return {
    bpmnEditor: wrapper.instance(),
    wrapper
  };
}<commit_msg>fix(client): fix failing test cases due to added properties panel width<commit_after>/* global sinon */

import React from 'react';

import { mount } from 'enzyme';

import {
  default as BpmnEditorWithCachedState,
  BpmnEditor
} from '../BpmnEditor';

import { SlotFillRoot } from 'src/app/slot-fill';

import diagramXML from './diagram.bpmn';

import { insertCSS } from 'test/helper';

insertCSS('test.css', '.test-content-container { position: relative; }');

describe('<BpmnEditor>', function() {

  let createCachedSpy;

  beforeEach(function() {
    createCachedSpy = sinon.spy(BpmnEditor, 'createCachedState');
  });

  afterEach(function() {
    createCachedSpy.restore();
  });

  it('should render', function() {
    const {
      bpmnEditor
    } = renderBpmnEditor(diagramXML);

    expect(bpmnEditor).to.exist;
  });

  // TODO(philippfromme): spy is not called if test isn't executed exclusively
  it.skip('should create modeler if no cached modeler', function() {

    const {
      bpmnEditor
    } = renderBpmnEditor(diagramXML);

    const {
      modeler
    } = bpmnEditor.getCached();

    expect(createCachedSpy).to.have.been.calledOnce;
    expect(modeler).to.exist;
  });

  it('should use existing modeler if cached modeler');

  it('#getXML', async function() {
    const {
      bpmnEditor
    } = renderBpmnEditor(diagramXML);

    const xml = await bpmnEditor.getXML();

    expect(xml).to.exist;
    expect(xml).to.eql(diagramXML);
  });

  describe('#exportAs', function() {

    let bpmnEditor;

    beforeEach(function() {
      bpmnEditor = renderBpmnEditor(diagramXML).bpmnEditor;
    });

    it('svg', async function() {
      const contents = await bpmnEditor.exportAs('svg');

      expect(contents).to.exist;
      expect(contents).to.equal('<svg />');
    });

    it('png', async function() {
      const contents = await bpmnEditor.exportAs('png');

      expect(contents).to.exist;
      expect(contents).to.contain('data:image/png');
    });

    it('jpeg', async function() {
      const contents = await bpmnEditor.exportAs('jpeg');

      expect(contents).to.exist;
      expect(contents).to.contain('data:image/jpeg');
    });

  });

  describe('layout', function() {

    it('should open properties panel', function() {

      // given
      const {
        bpmnEditor,
        wrapper
      } = renderBpmnEditor(diagramXML, {
        layout: {
          propertiesPanel: {
            open: false
          }
        }
      });

      const toggle = wrapper.find('.toggle');

      // when
      toggle.simulate('click');

      // then
      expect(bpmnEditor.state.layout.propertiesPanel.open).to.be.true;
    });

    it('should close properties panel', function() {

      // given
      const {
        bpmnEditor,
        wrapper
      } = renderBpmnEditor(diagramXML);

      const toggle = wrapper.find('.toggle');

      // when
      toggle.simulate('click');

      // then
      expect(bpmnEditor.state.layout.propertiesPanel.open).to.be.false;
    });

    it('should handle missing layout', function() {

      // when
      const {
        bpmnEditor
      } = renderBpmnEditor(diagramXML, {
        layout: {}
      });

      // then
      expect(bpmnEditor.state.layout).to.eql({
        minimap: {
          open: false
        },
        propertiesPanel: {
          open: true,
          width: 250
        }
      });
    });

    it('it should apply received layout', function() {

      // when
      const {
        bpmnEditor
      } = renderBpmnEditor(diagramXML, {
        layout: {
          minimap: {
            open: true
          },
          propertiesPanel: {
            open: false,
            width: 50
          }
        }
      });

      // then
      expect(bpmnEditor.state.layout).to.eql({
        minimap: {
          open: true
        },
        propertiesPanel: {
          open: false,
          width: 50
        }
      });
    });

  });

  describe('errors', function() {

    // TODO
    it('should handle template error');

    // TODO(philippfromme): why does import not return error?
    it.skip('should handle import error', function() {

      // given
      const onErrorSpy = sinon.spy();

      const errorXML = 'foo';

      // when
      renderBpmnEditor(errorXML, {
        onError: onErrorSpy
      });

      // then
      expect(onErrorSpy).to.have.been.called;
    });

    it('should handle export error', function() {
      // TODO(philippfromme): how to make #getXML throw?
    });

    it('should handle export error', function() {
      // TODO(philippfromme): how to make #exportAs throw?
    });

  });

});

function noop() {}

function renderBpmnEditor(xml, options = {}) {
  const {
    layout,
    onError,
    onLayoutChanged
  } = options;

  const slotFillRoot = mount(
    <SlotFillRoot>
      <BpmnEditorWithCachedState
        id="foo"
        xml={ xml }
        onLayoutChanged={ onLayoutChanged || noop }
        onError={ onError || noop }
        layout={ layout || {
          minimap: {
            open: false
          },
          propertiesPanel: {
            open: true
          }
        } } />
    </SlotFillRoot>
  );

  const wrapper = slotFillRoot.find(BpmnEditor);

  return {
    bpmnEditor: wrapper.instance(),
    wrapper
  };
}<|endoftext|>


<commit_before>'use strict';

function getRandomPosition(size) {
    return Math.floor(Math.random() * size);
}

var Chromosome = function (value) {
    var chromosomeLength = galgo.options.chromosomeLength;
    var mutationProbability = galgo.mutationProbability;
    var max = galgo.options.interval.max;
    var min = galgo.options.interval.min;

    var chromosome = {
        decode: decode,
        mutate: mutate,
        value: value
    };

    if (chromosome.value === undefined) {
        chromosome.value = generate(chromosomeLength);
    }

    return chromosome;

    function decode() {
        var decimalValue = parseInt(chromosome.value.toString().replace(/,/g, ''), 2);
        return min + (max - min) * (decimalValue / (Math.pow(2, chromosomeLength) - 1));
    }

    function mutate() {
        if (Math.random() > mutationProbability) {
            return;
        }

        // limit mutate to only one gene in chromosome: change bit
        var position = getRandomPosition(chromosomeLength);
        value[position] = ~~!value[position];
    }

    function generate(chromosomeLength) {
        var chromosomeValue = [];

        for (var i = 0; i < chromosomeLength; i++) {
            chromosomeValue.push(Math.round(Math.random()));
        }

        return chromosomeValue;
    }
};

var Individual = function (parent1, parent2) {
    var chromosomeLength = galgo.options.chromosomeLength;
    var individual = {};

    if (!parent1 && !parent2) {
        var newChromosome = new Chromosome();
        individual.chromosomes = {
            x: newChromosome,
            y: newChromosome
        };
    }
    else {
        parent1 = parent1 || parent2;
        parent2 = parent2 || parent1;

        individual.chromosomes = crossover(parent1, parent2);
        individual.chromosomes = mutate(individual.chromosomes);
    }

    individual.fitness = galgo.fitnessFunction(
        individual.chromosomes.x.decode(),
        individual.chromosomes.y.decode()
    );

    return individual;

    /////////////////////////////////////
    function crossover(parent1, parent2) {
        var position = getRandomPosition(chromosomeLength);

        var chromosomeXValue = parent1.chromosomes.x.value.slice(0, position).concat(
            parent2.chromosomes.x.value.slice(position));
        var chromosomeYValue = parent1.chromosomes.y.value.slice(0, position).concat(
            parent2.chromosomes.y.value.slice(position));

        return {
            x: new Chromosome(chromosomeXValue),
            y: new Chromosome(chromosomeYValue)
        };
    }

    function mutate(chromosomes) {
        chromosomes.x.mutate();
        chromosomes.y.mutate();
        return chromosomes;
    }
};

function selectBest(population) {
    var halfCutPosition = Math.ceil(population.length / 4) * 2;

    if (galgo.options.minimize){
        population.sort(function (curr, next) {
            return curr.fitness - next.fitness;
        });
    }
    else if (galgo.options.maximize) {
        population.sort(function (curr, next) {
            return next.fitness - curr.fitness ;
        });
    }

    var halfBest = population.slice(0, halfCutPosition);

    return halfBest;
}

function seedPopulation(populationSize) {
    var population = [];

    for (var i = 0; i < populationSize; i++) {
        population.push(new Individual());
    }

    return population;
}

function fitnessFunction(x, y) {
//    var z = (x - y) * (-x * Math.sin(Math.sqrt(Math.abs(x))) - y * Math.sin(Math.sqrt(Math.abs(y))));
    var z = x * x + 4 * y * y + 4 * y + x; // x² + 4y² + 4y + x
    return z;
}

function createOffspring(parent1, parent2) {
    var offspring = [];

    offspring.push(new Individual(parent1, parent2));
    offspring.push(new Individual(parent1, parent2));
    offspring.push(new Individual(parent1, parent2));
    offspring.push(new Individual(parent1, parent2));

    return offspring;
}

function run() {
    var startTimer = process.hrtime();

    var population = seedPopulation(galgo.options.populationSize);
    var result = {
        solution: {},
        history: [],
        profiler: {}
    };

    for (var ngen = 0; ngen < galgo.options.generationsQty; ngen++) {
        var bestParents = selectBest(population);

        result.history.push({
            generation: ngen + 1,
            individualsQty: population.length,
            x: bestParents[0].chromosomes.x.decode().toFixed(4),
            y: bestParents[0].chromosomes.y.decode().toFixed(4),
            z: bestParents[0].fitness
        });

        // Offspring generation
        var newPopulation = [];
        for (var i = 0; i < bestParents.length - 1; i += 2) {
            var offspring = createOffspring(bestParents[i], bestParents[i + 1]);
            newPopulation = newPopulation.concat(offspring);
        }
        population = newPopulation;
    }

    result.solution = {
        x: bestParents[0].chromosomes.x.decode().toFixed(4),
        y: bestParents[0].chromosomes.y.decode().toFixed(4),
        z: bestParents[0].fitness
    };

    result.profiler = {
        elapsedTime: parseFloat(process.hrtime(startTimer).join('.'))
    };

    return result;
}

var galgo = (function () {
    var geneticObject = {
        fitnessFunction: fitnessFunction,
        options: {
            chromosomeLength: 10,
            generationsQty: 25,
            mutationProbability: 0.02,
            populationSize: 250,
            maximize: false,
            minimize: true,

            // [min, max] objective function x, y variable
            interval: {
                min: -2,
                max: 2
            }
        },
        run: run
    };

    return geneticObject;
})();

module.exports = galgo;<commit_msg>refactored crossover routine to dynamic variables and DRY<commit_after>'use strict';

function getRandomPosition(size) {
    return Math.floor(Math.random() * size);
}

var Chromosome = function (value) {
    var chromosomeLength = galgo.options.chromosomeLength;
    var mutationProbability = galgo.mutationProbability;
    var max = galgo.options.interval.max;
    var min = galgo.options.interval.min;

    var chromosome = {
        decode: decode,
        mutate: mutate,
        value: value
    };

    if (chromosome.value === undefined) {
        chromosome.value = generate(chromosomeLength);
    }

    return chromosome;

    function decode() {
        var decimalValue = parseInt(chromosome.value.toString().replace(/,/g, ''), 2);
        return min + (max - min) * (decimalValue / (Math.pow(2, chromosomeLength) - 1));
    }

    function mutate() {
        if (Math.random() > mutationProbability) {
            return;
        }

        // limit mutate to only one gene in chromosome: change bit
        var position = getRandomPosition(chromosomeLength);
        value[position] = ~~!value[position];
    }

    function generate(chromosomeLength) {
        var chromosomeValue = [];

        for (var i = 0; i < chromosomeLength; i++) {
            chromosomeValue.push(Math.round(Math.random()));
        }

        return chromosomeValue;
    }
};

var Individual = function (parent1, parent2) {
    var chromosomeLength = galgo.options.chromosomeLength;
    var individual = {};

    if (!parent1 && !parent2) {
        var newChromosome = new Chromosome();
        individual.chromosomes = {
            x: newChromosome,
            y: newChromosome
        };
    }
    else {
        parent1 = parent1 || parent2;
        parent2 = parent2 || parent1;

        individual.chromosomes = crossover(parent1, parent2);
        individual.chromosomes = mutate(individual.chromosomes);
    }

    individual.fitness = galgo.fitnessFunction(
        individual.chromosomes.x.decode(),
        individual.chromosomes.y.decode()
    );

    return individual;

    /////////////////////////////////////
    function crossover(parent1, parent2) {
        var chromosomeIds = ['x', 'y'];
        var result = {};

        chromosomeIds.forEach(function(id){
            var position = getRandomPosition(chromosomeLength);
            var value = parent1.chromosomes[id].value.slice(0, position).concat(
                parent2.chromosomes[id].value.slice(position));
            result[id] = new Chromosome(value);
        });

        return result;
    }

    function mutate(chromosomes) {
        chromosomes.x.mutate();
        chromosomes.y.mutate();
        return chromosomes;
    }
};

function selectBest(population) {
    var halfCutPosition = Math.ceil(population.length / 4) * 2;

    if (galgo.options.minimize){
        population.sort(function (curr, next) {
            return curr.fitness - next.fitness;
        });
    }
    else if (galgo.options.maximize) {
        population.sort(function (curr, next) {
            return next.fitness - curr.fitness ;
        });
    }

    var halfBest = population.slice(0, halfCutPosition);

    return halfBest;
}

function seedPopulation(populationSize) {
    var population = [];

    for (var i = 0; i < populationSize; i++) {
        population.push(new Individual());
    }

    return population;
}

function fitnessFunction(x, y) {
//    var z = (x - y) * (-x * Math.sin(Math.sqrt(Math.abs(x))) - y * Math.sin(Math.sqrt(Math.abs(y))));
    var z = x * x + 4 * y * y + 4 * y + x; // x² + 4y² + 4y + x
    return z;
}

function createOffspring(parent1, parent2) {
    var offspring = [];

    offspring.push(new Individual(parent1, parent2));
    offspring.push(new Individual(parent1, parent2));
    offspring.push(new Individual(parent1, parent2));
    offspring.push(new Individual(parent1, parent2));

    return offspring;
}

function run() {
    var startTimer = process.hrtime();

    var population = seedPopulation(galgo.options.populationSize);
    var result = {
        solution: {},
        history: [],
        profiler: {}
    };

    for (var ngen = 0; ngen < galgo.options.generationsQty; ngen++) {
        var bestParents = selectBest(population);

        result.history.push({
            generation: ngen + 1,
            individualsQty: population.length,
            x: bestParents[0].chromosomes.x.decode().toFixed(4),
            y: bestParents[0].chromosomes.y.decode().toFixed(4),
            z: bestParents[0].fitness
        });

        // Offspring generation
        var newPopulation = [];
        for (var i = 0; i < bestParents.length - 1; i += 2) {
            var offspring = createOffspring(bestParents[i], bestParents[i + 1]);
            newPopulation = newPopulation.concat(offspring);
        }
        population = newPopulation;
    }

    result.solution = {
        x: bestParents[0].chromosomes.x.decode().toFixed(4),
        y: bestParents[0].chromosomes.y.decode().toFixed(4),
        z: bestParents[0].fitness
    };

    result.profiler = {
        elapsedTime: parseFloat(process.hrtime(startTimer).join('.'))
    };

    return result;
}

var galgo = (function () {
    var geneticObject = {
        fitnessFunction: fitnessFunction,
        options: {
            chromosomeLength: 10,
            generationsQty: 25,
            mutationProbability: 0.02,
            populationSize: 250,
            maximize: false,
            minimize: true,

            // [min, max] objective function x, y variable
            interval: {
                min: -2,
                max: 2
            }
        },
        run: run
    };

    return geneticObject;
})();

module.exports = galgo;<|endoftext|>


<commit_before>import { SelectionState, EditorState } from 'draft-js';

// Get selection text's client rectangle
function getSelectionRect(selected) {
  if (!selected) return null;

  const range = selected.getRangeAt ? selected.getRangeAt(0) : selected;

  const _rect = range.getBoundingClientRect();
  let rect = _rect && _rect.top ? _rect : range.getClientRects()[0];// selected.getRangeAt(0).getBoundingClientRect()
  if (!rect) {
    if (selected.anchorNode && selected.anchorNode.getBoundingClientRect) {
      rect = selected.anchorNode.getBoundingClientRect();
      rect.isEmptyline = true;
    } else if (selected.startContainer && selected.startContainer.getBoundingClientRect) {
      rect = selected.startContainer.getBoundingClientRect();
      rect.isEmptyline = true;
    } else {
      return null;
    }
  }

  return rect;
}

// Set selection of editor to next/previous block
export default (getEditorState, setEditorState, previousActiveBlock, mode, event) => {
  const selection = getEditorState().getSelection();
  const editorState = getEditorState();
  const activeBlock = mode === 'previous'
    ? editorState.getCurrentContent().getBlockBefore(selection.getAnchorKey())
    : editorState.getCurrentContent().getBlockAfter(selection.getAnchorKey());

  if (event) {
    const range = window.getSelection().getRangeAt(0);
    const postRange = document.createRange();
    postRange.selectNodeContents(event.target);
    if (mode === 'previous') {
      postRange.setEnd(range.startContainer, range.startOffset);
    } else {
      postRange.setStart(range.endContainer, range.endOffset);
    }

    const rect = getSelectionRect(range);
    const rectPost = getSelectionRect(postRange);

    const hasTopChanged = rect.top === rectPost.top;
    const nextIsDiv = (mode === 'previous' ? postRange.startContainer : postRange.endContainer).nodeName.toLowerCase() === 'div';

    if (activeBlock && (hasTopChanged || nextIsDiv)) {
      event.preventDefault();
      setEditorState(EditorState.forceSelection(editorState, new SelectionState({
        anchorKey: activeBlock.get('key'),
        anchorOffset: activeBlock.get('length') || 0,
        focusKey: activeBlock.get('key'),
        focusOffset: activeBlock.get('length') || 0,
        isBackward: false,
      })));
      return activeBlock;
    }
  } return undefined;
};
<commit_msg>Improved focus-plugin behaviour<commit_after>import { SelectionState, EditorState } from 'draft-js';

const findParentNode = (node, filter) => {
  if (!node) return null;
  return node.parentElement && filter(node.parentElement)
    ? node.parentElement
    : findParentNode(node.parentElement, filter);
};

// Set selection of editor to next/previous block
export default (getEditorState, setEditorState, previousActiveBlock, mode, event) => {
  const selection = getEditorState().getSelection();
  const editorState = getEditorState();
  const activeBlock = mode === 'previous'
    ? editorState.getCurrentContent().getBlockBefore(selection.getAnchorKey())
    : editorState.getCurrentContent().getBlockAfter(selection.getAnchorKey());

  if (event) {
    let atLimit = false;
    if (window.getSelection) {
      const sel = window.getSelection();
      if (sel.rangeCount) {
        const selRange = sel.getRangeAt(0);
        const testRange = selRange.cloneRange();
        // Get parent node for orientation
        const parent = findParentNode(sel.anchorNode, x => x.hasAttribute('data-block'));
        testRange.selectNodeContents(parent);

        if (mode === 'previous') {
          testRange.setEnd(selRange.startContainer, selRange.startOffset);
          atLimit = testRange.toString() === '' || testRange.getBoundingClientRect().top === selRange.getBoundingClientRect().top;
        } else {
          testRange.setStart(selRange.endContainer, selRange.endOffset);
          atLimit = (testRange.toString() === '') || testRange.getBoundingClientRect().top === selRange.getBoundingClientRect().top;
        }
      }
    }/* else if (document.selection && document.selection.type !== 'Control') {
      const selRange = document.selection.createRange();
      const testRange = selRange.duplicate();
      const parent = findParentNode(selRange.anchorNode, x => x.hasAttribute('data-block'));

      testRange.moveToElementText(parent);
      testRange.setEndPoint('EndToStart', selRange);
      info.atStart = (testRange.text === '');

      testRange.moveToElementText(parent);
      testRange.setEndPoint('StartToEnd', selRange);
      info.atEnd = (testRange.text === '');
    }*/

    if (activeBlock && activeBlock.get('type') !== 'unstyled' && atLimit) {
      event.preventDefault();
      setEditorState(EditorState.forceSelection(editorState, new SelectionState({
        anchorKey: activeBlock.get('key'),
        anchorOffset: activeBlock.get('length') || 0,
        focusKey: activeBlock.get('key'),
        focusOffset: activeBlock.get('length') || 0,
        isBackward: false,
      })));
      return activeBlock;
    }
  } return undefined;
};
<|endoftext|>


<commit_before>/*global cosh, tanh, toRadians*/

function getSpeedWithoutAirResistance(f_Res, weight, init_velo, terrain_length, points_max) {
    "use strict";
    var i = 1,
        acceleration = f_Res / weight,
        max_time = (-init_velo / acceleration) + Math.sqrt(init_velo * init_velo + 2 * acceleration * terrain_length / (acceleration * acceleration)),

        res = [];
    res[0] = {};
    res[0].time = 0;
    res[0].speed = init_velo;
    res[0].path = 0;
    for (i; i <= points_max - 1; i = i + 1) {
        res[i] = {};
        res[i].time = max_time / (points_max) * (i + 1);
        res[i].speed = acceleration * res[i].time + init_velo;
        res[i].path = 0.5 * acceleration * res[i].time * res[i].time + init_velo * res[i].time;
    }
    res[res.length - 1].path = terrain_length;
    return res;
}

function getSpeedApproximateAirResistance(steps, f_Res, wheight, init_velo, terrain_length, area, density, cw, f_Gleit, f_Hangab) {
    "use strict";
    var i = 1,
        acceleration = f_Res / wheight,
        last_velo = init_velo,
        pastPath = 0,
        pastSpeed = 0,
        f_Air = 0,
        res = [];
    res[0] = {};
    res[0].time = 0;
    res[0].speed = init_velo;
    res[0].path = 0;
    do {
        res[i] = {};
        res[i].time = (i + 1) * steps;
        res[i].speed = acceleration * steps + last_velo;
        res[i].path = pastPath + 0.5 * acceleration * steps * steps + last_velo * steps;
        last_velo = res[i].speed;
        f_Air = area * density * cw * res[i].speed * res[i].speed / 2;
        f_Res = f_Hangab - f_Air - f_Gleit;
        acceleration = f_Res / wheight;
        pastPath = res[i].path;
        i = i + 1;
    } while (res[res.length - 1].path < terrain_length);
    res[res.length - 1].path = terrain_length;

    return res;
}

function getWithAirResistance(steps, f_Res, weight, init_velo, area, density, cw, terrain_length) {
    "use strict";
    var i = 1,

        res = [];
    res[0] = {};
    res[0].time = 0;
    res[0].speed = init_velo;
    res[0].path = 0;
    do {
        res[i] = {};
        res[i].time = (i + 1) * steps;
        res[i].speed = init_velo + Math.sqrt(f_Res / (0.5 * area * cw * density)) * tanh(res[i].time * Math.sqrt((f_Res / weight) * 0.5 * area * cw * density / weight));
        res[i].path = weight / (0.5 * area * cw * density) * Math.log(cosh(res[i].time * Math.sqrt((f_Res / weight) * 0.5 * area * cw * density / weight)));
        i = i + 1;
    } while (res[res.length - 1].path < terrain_length);
    res[res.length - 1].path = terrain_length;

    return res;
}

function analyze(requestJSon) {
    "use strict";
    var res = {
            forRequestID: requestJSon.requestID
        },
        f_Gewicht = 0,
        f_Hangab = 0,
        f_Normal = 0,

        f_Haft = 0,
        f_Gleit = 0,

        f_Air = 0,

        f_Res = 0;

    if (!isNaN(requestJSon.terrain.angle) && !isNaN(requestJSon.terrain.gravitation) && !isNaN(requestJSon.terrain.length) && !isNaN(requestJSon.subject.weight) && !isNaN(requestJSon.subject.area) && !isNaN(requestJSon.subject.cw) && !isNaN(requestJSon.subject.init_velo) && !isNaN(requestJSon.subject.force) && !isNaN(requestJSon.resistance.stationary) && !isNaN(requestJSon.resistance.underway) && !isNaN(requestJSon.fluid.density) && !isNaN(requestJSon.points.max) && !isNaN(requestJSon.points.steps)) {
        f_Gewicht = requestJSon.subject.weight * requestJSon.terrain.gravitation; //Gewichtskraft in Newton [N]
        f_Hangab = f_Gewicht * Math.sin(toRadians(requestJSon.terrain.angle)); //Hangabtriebskraft in [N]
        f_Normal = f_Gewicht * Math.cos(toRadians(requestJSon.terrain.angle)); //Normalkraft in [N]

        f_Haft = f_Normal * requestJSon.resistance.stationary; //Haftreibungskraft in [N]
        f_Gleit = f_Normal * requestJSon.resistance.underway; //Gleitreibungskraft in [N]

        f_Air = requestJSon.subject.area * requestJSon.fluid.density * requestJSon.subject.cw * requestJSon.subject.init_velo * requestJSon.subject.init_velo / 2;

        f_Res = f_Hangab - f_Haft;

        if (requestJSon.subject.init_velo > 0 || f_Res > 0) {
            f_Res = f_Hangab - f_Gleit + requestJSon.subject.force;

            res.withoutAirResistance = getSpeedWithoutAirResistance(f_Res, requestJSon.subject.weight, requestJSon.subject.init_velo, requestJSon.terrain.length, requestJSon.points.max);

            f_Res = f_Hangab - f_Air - f_Haft;
            if (f_Res > 0) {
                f_Res = f_Hangab - f_Air - f_Gleit + requestJSon.subject.force;

                res.approximateAirResistance = getSpeedApproximateAirResistance(requestJSon.points.steps, f_Res, requestJSon.subject.weight, requestJSon.subject.init_velo, requestJSon.terrain.length, requestJSon.subject.area, requestJSon.fluid.density, requestJSon.subject.cw, f_Gleit, f_Hangab);

                f_Res = requestJSon.subject.force + f_Hangab - f_Gleit;
                res.withAirResistance = getWithAirResistance(requestJSon.points.steps, f_Res, requestJSon.subject.weight, requestJSon.subject.init_velo, requestJSon.subject.area, requestJSon.fluid.density, requestJSon.subject.cw, requestJSon.terrain.length);
            }
        }
    }
    if (res.approximateAirResistance === null) {
        res.approximateAirResistance = [];
        res.approximateAirResistance = [{
            speed: 0,
            path: 0,
            time: 0
        }];
    }

    if (res.withAirResistance === null) {
        res.withAirResistance = [{
            speed: 0,
            path: 0,
            time: 0
        }];
    }

    if (res.withoutAirResistance === null) {
        res.withoutAirResistance = [{
            speed: 0,
            path: 0,
            time: 0
        }];
    }

    return res;
}<commit_msg>corrected max time calculation<commit_after>/*global cosh, tanh, toRadians*/

function getSpeedWithoutAirResistance(f_Res, weight, init_velo, terrain_length, points_max) {
    "use strict";
    var i = 1,
        acceleration = f_Res / weight,
        max_time = (-init_velo + Math.sqrt(init_velo * init_velo + 2 * acceleration * terrain_length)) / acceleration,
        //max_time = (-init_velo / acceleration) + Math.sqrt(init_velo * init_velo + 2 * acceleration * terrain_length / (acceleration * acceleration)),

        res = [];
    res[0] = {};
    res[0].time = 0;
    res[0].speed = init_velo;
    res[0].path = 0;
    for (i; i <= points_max - 1; i = i + 1) {
        res[i] = {};
        res[i].time = max_time / (points_max) * (i + 1);
        res[i].speed = acceleration * res[i].time + init_velo;
        res[i].path = 0.5 * acceleration * res[i].time * res[i].time + init_velo * res[i].time;
    }
    res[res.length - 1].path = terrain_length;
    return res;
}

function getSpeedApproximateAirResistance(steps, f_Res, wheight, init_velo, terrain_length, area, density, cw, f_Gleit, f_Hangab) {
    "use strict";
    var i = 1,
        acceleration = f_Res / wheight,
        last_velo = init_velo,
        pastPath = 0,
        pastSpeed = 0,
        f_Air = 0,
        res = [];
    res[0] = {};
    res[0].time = 0;
    res[0].speed = init_velo;
    res[0].path = 0;
    do {
        res[i] = {};
        res[i].time = (i + 1) * steps;
        res[i].speed = acceleration * steps + last_velo;
        res[i].path = pastPath + 0.5 * acceleration * steps * steps + last_velo * steps;
        last_velo = res[i].speed;
        f_Air = area * density * cw * res[i].speed * res[i].speed / 2;
        f_Res = f_Hangab - f_Air - f_Gleit;
        acceleration = f_Res / wheight;
        pastPath = res[i].path;
        i = i + 1;
    } while (res[res.length - 1].path < terrain_length);
    res[res.length - 1].path = terrain_length;

    return res;
}

function getWithAirResistance(steps, f_Res, weight, init_velo, area, density, cw, terrain_length) {
    "use strict";
    var i = 1,

        res = [];
    res[0] = {};
    res[0].time = 0;
    res[0].speed = init_velo;
    res[0].path = 0;
    do {
        res[i] = {};
        res[i].time = (i + 1) * steps;
        res[i].speed = init_velo + Math.sqrt(f_Res / (0.5 * area * cw * density)) * tanh(res[i].time * Math.sqrt((f_Res / weight) * 0.5 * area * cw * density / weight));
        res[i].path = weight / (0.5 * area * cw * density) * Math.log(cosh(res[i].time * Math.sqrt((f_Res / weight) * 0.5 * area * cw * density / weight)));
        i = i + 1;
    } while (res[res.length - 1].path < terrain_length);
    res[res.length - 1].path = terrain_length;

    return res;
}

function analyze(requestJSon) {
    "use strict";
    var res = {
            forRequestID: requestJSon.requestID
        },
        f_Gewicht = 0,
        f_Hangab = 0,
        f_Normal = 0,

        f_Haft = 0,
        f_Gleit = 0,

        f_Air = 0,

        f_Res = 0;

    if (!isNaN(requestJSon.terrain.angle) && !isNaN(requestJSon.terrain.gravitation) && !isNaN(requestJSon.terrain.length) && !isNaN(requestJSon.subject.weight) && !isNaN(requestJSon.subject.area) && !isNaN(requestJSon.subject.cw) && !isNaN(requestJSon.subject.init_velo) && !isNaN(requestJSon.subject.force) && !isNaN(requestJSon.resistance.stationary) && !isNaN(requestJSon.resistance.underway) && !isNaN(requestJSon.fluid.density) && !isNaN(requestJSon.points.max) && !isNaN(requestJSon.points.steps)) {
        f_Gewicht = requestJSon.subject.weight * requestJSon.terrain.gravitation; //Gewichtskraft in Newton [N]
        f_Hangab = f_Gewicht * Math.sin(toRadians(requestJSon.terrain.angle)); //Hangabtriebskraft in [N]
        f_Normal = f_Gewicht * Math.cos(toRadians(requestJSon.terrain.angle)); //Normalkraft in [N]

        f_Haft = f_Normal * requestJSon.resistance.stationary; //Haftreibungskraft in [N]
        f_Gleit = f_Normal * requestJSon.resistance.underway; //Gleitreibungskraft in [N]

        f_Air = requestJSon.subject.area * requestJSon.fluid.density * requestJSon.subject.cw * requestJSon.subject.init_velo * requestJSon.subject.init_velo / 2;

        f_Res = f_Hangab - f_Haft;

        if (requestJSon.subject.init_velo > 0 || f_Res > 0) {
            f_Res = f_Hangab - f_Gleit + requestJSon.subject.force;

            res.withoutAirResistance = getSpeedWithoutAirResistance(f_Res, requestJSon.subject.weight, requestJSon.subject.init_velo, requestJSon.terrain.length, requestJSon.points.max);

            f_Res = f_Hangab - f_Air - f_Haft;
            if (f_Res > 0) {
                f_Res = f_Hangab - f_Air - f_Gleit + requestJSon.subject.force;

                res.approximateAirResistance = getSpeedApproximateAirResistance(requestJSon.points.steps, f_Res, requestJSon.subject.weight, requestJSon.subject.init_velo, requestJSon.terrain.length, requestJSon.subject.area, requestJSon.fluid.density, requestJSon.subject.cw, f_Gleit, f_Hangab);

                f_Res = requestJSon.subject.force + f_Hangab - f_Gleit;
                res.withAirResistance = getWithAirResistance(requestJSon.points.steps, f_Res, requestJSon.subject.weight, requestJSon.subject.init_velo, requestJSon.subject.area, requestJSon.fluid.density, requestJSon.subject.cw, requestJSon.terrain.length);
            }
        }
    }
    if (res.approximateAirResistance === null) {
        res.approximateAirResistance = [];
        res.approximateAirResistance = [{
            speed: 0,
            path: 0,
            time: 0
        }];
    }

    if (res.withAirResistance === null) {
        res.withAirResistance = [{
            speed: 0,
            path: 0,
            time: 0
        }];
    }

    if (res.withoutAirResistance === null) {
        res.withoutAirResistance = [{
            speed: 0,
            path: 0,
            time: 0
        }];
    }

    return res;
}<|endoftext|>