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

'use strict';

// MODULES //

var hasOwnProp = require( '@stdlib/assert/has-own-property' );
var isObject = require( '@stdlib/assert/is-plain-object' );
var isBoolean = require( '@stdlib/assert/is-boolean' ).isPrimitive;
var isArray = require( '@stdlib/assert/is-array' );
var isNonNegativeInteger = require( '@stdlib/assert/is-nonnegative-integer' ).isPrimitive;
var isndarrayLike = require( '@stdlib/assert/is-ndarray-like' );
var shape2strides = require( '@stdlib/ndarray/base/shape2strides' );
var strides2offset = require( '@stdlib/ndarray/base/strides2offset' );
var strides2order = require( '@stdlib/ndarray/base/strides2order' );
var numel = require( '@stdlib/ndarray/base/numel' );
var ctor = require( '@stdlib/ndarray/ctor' );
var mctor = require( '@stdlib/ndarray/memoized-ctor' );
var isDataType = require( '@stdlib/ndarray/base/assert/is-data-type' );
var isOrder = require( '@stdlib/ndarray/base/assert/is-order' );
var isCastingMode = require( '@stdlib/ndarray/base/assert/is-casting-mode' );
var isAllowedCast = require( '@stdlib/ndarray/base/assert/is-allowed-data-type-cast' );
var createBuffer = require( '@stdlib/ndarray/base/buffer' );
var getType = require( '@stdlib/ndarray/base/buffer-dtype' );
var arrayShape = require( '@stdlib/array/shape' );
var flattenArray = require( '@stdlib/utils/flatten-array' );
var isArrayLikeObject = require( './is_array_like_object.js' );
var defaults = require( './defaults.json' );
var castBuffer = require( './cast_buffer.js' );
var copyView = require( './copy_view.js' );
var expandShape = require( './expand_shape.js' );
var expandStrides = require( './expand_strides.js' );

// MAIN //

/**
* Returns a multidimensional array.
*
* @param {(ArrayLikeObject|TypedArrayLike|Buffer|ndarrayLike)} [buffer] - data source
* @param {Options} [options] - function options
* @param {(ArrayLikeObject|TypedArrayLike|Buffer|ndarrayLike)} [options.buffer] - data source
* @param {string} [options.dtype="float64"] - underlying storage data type (if the input data is not of the same type, this option specifies the data type to which to cast the input data)
* @param {string} [options.order="row-major"] - specifies the memory layout of the array as either row-major (C-style) or column-major (Fortran-style)
* @param {NonNegativeIntegerArray} [options.shape] - array shape
* @param {boolean} [options.codegen=true] - boolean indicating whether to use code generation
* @param {string} [options.mode="throw"] - specifies how to handle indices which exceed array dimensions
* @param {StringArray} [options.submode=["throw"]] - specifies how to handle subscripts which exceed array dimensions on a per dimension basis
* @param {boolean} [options.copy=false] - boolean indicating whether to copy source data to a new data buffer
* @param {boolean} [options.flatten=true] - boolean indicating whether to automatically flatten generic array data sources
* @param {NonNegativeInteger} [options.ndmin=0] - minimum number of dimensions
* @param {string} [options.casting="safe"] - casting rule used to determine what constitutes an acceptable cast
* @throws {TypeError} options argument must be an object
* @throws {TypeError} must provide valid options
* @throws {Error} must provide either an array shape, data source, or both
* @throws {Error} invalid cast
* @throws {RangeError} data source must be compatible with specified meta data
* @returns {ndarray} ndarray instance
*
* @example
* var arr = array( [ [ 1, 2 ], [ 3, 4 ] ] );
* // returns <ndarray>
*
* var v = arr.get( 0, 0 );
* // returns 1
*
* @example
* var opts = {
*     'dtype': 'generic',
*     'flatten': false
* };
*
* var arr = array( [ [ 1, 2 ], [ 3, 4 ] ], opts );
* // returns <ndarray>
*
* var v = arr.get( 0 );
* // returns [ 1, 2 ]
*
* @example
* var Float64Array = require( '@stdlib/array/float64' );
*
* var opts = {
*     'shape': [ 2, 2 ]
* };
*
* var arr = array( new Float64Array( [ 1.0, 2.0, 3.0, 4.0 ] ), opts );
* // returns <ndarray>
*
* var v = arr.get( 0, 0 );
* // returns 1.0
*/
function array() {
	var ndarray;
	var options;
	var strides;
	var buffer;
	var offset;
	var order;
	var dtype;
	var btype;
	var shape;
	var ndims;
	var nopts;
	var opts;
	var len;
	var ord;
	var FLG;

	if ( arguments.length === 1 ) {
		if ( isArrayLikeObject( arguments[ 0 ] ) ) {
			buffer = arguments[ 0 ];
			options = {};
		} else {
			options = arguments[ 0 ];
			if ( !isObject( options ) ) {
				throw new TypeError( 'invalid argument. Must provide either a valid data source, options argument, or both. Value: `' + options + '`.' );
			}
			if ( hasOwnProp( options, 'buffer' ) ) {
				buffer = options.buffer;
				if ( !isArrayLikeObject( buffer ) ) { // weak test
					throw new TypeError( 'invalid option. `buffer` option must be an array-like object, typed-array-like, a Buffer, or an ndarray. Option: `' + buffer + '`.' );
				}
			}
		}
	} else {
		buffer = arguments[ 0 ];
		if ( !isArrayLikeObject( buffer ) ) { // weak test
			throw new TypeError( 'invalid option. Data source must be an array-like object, typed-array-like, a Buffer, or an ndarray. Value: `' + buffer + '`.' );
		}
		options = arguments[ 1 ];
		if ( !isObject( options ) ) {
			throw new TypeError( 'invalid argument. Options argument must be an object. Value: `' + options + '`.' );
		}
		// Note: we ignore whether `options` has a `buffer` property
	}
	if ( buffer ) {
		if ( isndarrayLike( buffer ) ) {
			btype = buffer.dtype;
			FLG = true;
		} else {
			btype = getType( buffer );
			FLG = false;
		}
	}
	nopts = {};
	opts = {};

	// Validate some options before others...
	if ( hasOwnProp( options, 'casting' ) ) {
		opts.casting = options.casting;
		if ( !isCastingMode( opts.casting ) ) {
			throw new TypeError( 'invalid option. `casting` option must be a recognized casting mode. Option: `' + opts.casting + '`.' );
		}
	} else {
		opts.casting = defaults.casting;
	}
	if ( hasOwnProp( options, 'flatten' ) ) {
		opts.flatten = options.flatten;
		if ( !isBoolean( opts.flatten ) ) {
			throw new TypeError( 'invalid option. `flatten` option must be a boolean. Option: `' + opts.flatten + '`.' );
		}
	} else {
		opts.flatten = defaults.flatten;
	}
	if ( hasOwnProp( options, 'ndmin' ) ) {
		opts.ndmin = options.ndmin;
		if ( !isNonNegativeInteger( opts.ndmin ) ) {
			throw new TypeError( 'invalid option. `ndmin` option must be a nonnegative integer. Option: `' + opts.ndmin + '`.' );
		}
		// TODO: validate that minimum number of dimensions does not exceed the maximum number of possible dimensions (in theory, infinite; in practice, determined by max array length; see https://github.com/stdlib-js/stdlib/blob/ac350059877c036640775d6b30d0e98e840d07cf/lib/node_modules/%40stdlib/ndarray/ctor/lib/main.js#L57)
	} else {
		opts.ndmin = defaults.ndmin;
	}

	// Validate the remaining options...
	if ( hasOwnProp( options, 'dtype' ) ) {
		dtype = options.dtype;
		if ( !isDataType( dtype ) ) {
			throw new TypeError( 'invalid option. `dtype` option must be a recognized data type. Option: `' + dtype + '`.' );
		}
		if ( btype && !isAllowedCast( btype, dtype, opts.casting ) ) {
			throw new Error( 'invalid option. Data type cast is not allowed. Casting mode: `' + opts.casting + '`. From: `' + btype + '`. To: `' + dtype + '`.' );
		}
	} else if ( btype ) {
		// Only cast generic array data sources when not provided an ndarray...
		if ( !FLG && btype === 'generic' ) {
			dtype = defaults.dtype;
		} else {
			dtype = btype;
		}
	} else {
		dtype = defaults.dtype;
	}
	if ( hasOwnProp( options, 'order' ) ) {
		order = options.order;
		if ( order === 'any' || order === 'same' ) {
			if ( FLG ) {
				// If the user indicated that "any" order suffices (meaning the user does not care about ndarray order), then we use the default order, unless the input ndarray is either unequivocally "row-major" or "column-major" or configured as such....
				if ( order === 'any' ) {
					// Compute the layout order in order to ascertain whether an ndarray can be considered both "row-major" and "column-major":
					ord = strides2order( buffer.strides );

					// If the ndarray can be considered both "row-major" and "column-major", then use the default order; otherwise, use the ndarray's stated layout order...
					if ( ord === 'both' ) {
						order = defaults.order;
					} else {
						order = buffer.order;
					}
				}
				// Otherwise, use the same order as the provided ndarray...
				else if ( order === 'same' ) {
					order = buffer.order;
				}
			} else {
				order = defaults.order;
			}
		} else if ( !isOrder( order ) ) {
			throw new TypeError( 'invalid option. `order` option must be a recognized order. Option: `' + order + '`.' );
		}
	} else {
		order = defaults.order;
	}
	if ( hasOwnProp( options, 'codegen' ) ) {
		nopts.codegen = options.codegen;
	} else {
		nopts.codegen = defaults.codegen;
	}
	if ( hasOwnProp( options, 'mode' ) ) {
		nopts.mode = options.mode;
	} else {
		nopts.mode = defaults.mode;
	}
	if ( hasOwnProp( options, 'submode' ) ) {
		nopts.submode = options.submode;
	} else {
		nopts.submode = [ nopts.mode ];
	}
	if ( hasOwnProp( options, 'copy' ) ) {
		opts.copy = options.copy;
		if ( !isBoolean( opts.copy ) ) {
			throw new TypeError( 'invalid option. `copy` option must be a boolean. Option: `' + opts.copy + '`.' );
		}
	} else {
		opts.copy = defaults.copy;
	}
	// If not provided a shape, infer from a provided data source...
	if ( hasOwnProp( options, 'shape' ) ) {
		shape = options.shape;
		if ( !isArrayLikeObject( shape ) ) { // weak test
			throw new TypeError( 'invalid option. `shape` option must be an array-like object containing nonnegative integers. Option: `' + shape + '`.' );
		}
		ndims = shape.length;
		len = numel( shape );
	} else if ( buffer ) {
		if ( FLG ) {
			shape = buffer.shape;
			ndims = buffer.ndims;
			len = buffer.length;
		} else if ( opts.flatten && isArray( buffer ) ) {
			shape = arrayShape( buffer );
			ndims = shape.length;
			len = numel( shape );
		} else {
			ndims = 1;
			len = buffer.length;
			shape = [ len ]; // assume a 1-dimensional array (vector)
		}
	} else {
		throw new Error( 'invalid arguments. Must provide either a data source, array shape, or both.' );
	}
	// Adjust the array shape to satisfy the minimum number of dimensions...
	if ( ndims < opts.ndmin ) {
		shape = expandShape( ndims, shape, opts.ndmin );
		ndims = opts.ndmin;
	}
	// If not provided a data buffer, create it; otherwise, see if we need to cast a provided data buffer to another data type or perform a copy...
	if ( FLG ) {
		if ( buffer.length !== len ) {
			throw new RangeError( 'invalid arguments. Array shape is incompatible with provided data source. Number of data source elements does not match array shape.' );
		}
		if ( btype !== dtype || opts.copy ) {
			buffer = copyView( buffer, dtype );
		} else {
			strides = buffer.strides;
			offset = buffer.offset;
			buffer = buffer.data;
			if ( strides.length < ndims ) {
				// Account for augmented dimensions (note: expanding the strides array to account for prepended singleton dimensions does **not** affect the index offset):
				strides = expandStrides( ndims, shape, strides, order );
			}
		}
	} else if ( buffer ) {
		if ( btype === 'generic' && opts.flatten ) {
			buffer = flattenArray( buffer );
		}
		if ( buffer.length !== len ) {
			throw new RangeError( 'invalid arguments. Array shape is incompatible with provided data source. Number of data source elements does not match array shape.' );
		}
		if ( btype !== dtype || opts.copy ) {
			buffer = castBuffer( buffer, len, dtype );
		}
	} else {
		buffer = createBuffer( dtype, len );
	}
	// If we have yet to determine array strides, we assume that we can compute the strides, along with the index offset, for a **contiguous** data source based solely on the array shape and specified memory layout order...
	if ( strides === void 0 ) {
		strides = shape2strides( shape, order );
		offset = strides2offset( shape, strides );
	}
	// Use a heuristic to avoid memoization of highly-specialized ndarray constructors, thus effectively introducing "fast" and "slow" ndarray construction paths...
	if ( nopts.submode.length < 3 ) {
		ndarray = mctor( dtype, ndims, nopts );
		return new ndarray( buffer, shape, strides, offset, order );
	}
	ndarray = ctor( dtype, ndims, nopts );
	return new ndarray( buffer, shape, strides, offset, order );
}

// EXPORTS //

module.exports = array;
<commit_msg>Add TODO item<commit_after>/**
* @license Apache-2.0
*
* Copyright (c) 2018 The Stdlib Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

'use strict';

// MODULES //

var hasOwnProp = require( '@stdlib/assert/has-own-property' );
var isObject = require( '@stdlib/assert/is-plain-object' );
var isBoolean = require( '@stdlib/assert/is-boolean' ).isPrimitive;
var isArray = require( '@stdlib/assert/is-array' );
var isNonNegativeInteger = require( '@stdlib/assert/is-nonnegative-integer' ).isPrimitive;
var isndarrayLike = require( '@stdlib/assert/is-ndarray-like' );
var shape2strides = require( '@stdlib/ndarray/base/shape2strides' );
var strides2offset = require( '@stdlib/ndarray/base/strides2offset' );
var strides2order = require( '@stdlib/ndarray/base/strides2order' );
var numel = require( '@stdlib/ndarray/base/numel' );
var ctor = require( '@stdlib/ndarray/ctor' );
var mctor = require( '@stdlib/ndarray/memoized-ctor' );
var isDataType = require( '@stdlib/ndarray/base/assert/is-data-type' );
var isOrder = require( '@stdlib/ndarray/base/assert/is-order' );
var isCastingMode = require( '@stdlib/ndarray/base/assert/is-casting-mode' );
var isAllowedCast = require( '@stdlib/ndarray/base/assert/is-allowed-data-type-cast' );
var createBuffer = require( '@stdlib/ndarray/base/buffer' );
var getType = require( '@stdlib/ndarray/base/buffer-dtype' );
var arrayShape = require( '@stdlib/array/shape' );
var flattenArray = require( '@stdlib/utils/flatten-array' );
var isArrayLikeObject = require( './is_array_like_object.js' );
var defaults = require( './defaults.json' );
var castBuffer = require( './cast_buffer.js' );
var copyView = require( './copy_view.js' );
var expandShape = require( './expand_shape.js' );
var expandStrides = require( './expand_strides.js' );

// MAIN //

/**
* Returns a multidimensional array.
*
* @param {(ArrayLikeObject|TypedArrayLike|Buffer|ndarrayLike)} [buffer] - data source
* @param {Options} [options] - function options
* @param {(ArrayLikeObject|TypedArrayLike|Buffer|ndarrayLike)} [options.buffer] - data source
* @param {string} [options.dtype="float64"] - underlying storage data type (if the input data is not of the same type, this option specifies the data type to which to cast the input data)
* @param {string} [options.order="row-major"] - specifies the memory layout of the array as either row-major (C-style) or column-major (Fortran-style)
* @param {NonNegativeIntegerArray} [options.shape] - array shape
* @param {boolean} [options.codegen=true] - boolean indicating whether to use code generation
* @param {string} [options.mode="throw"] - specifies how to handle indices which exceed array dimensions
* @param {StringArray} [options.submode=["throw"]] - specifies how to handle subscripts which exceed array dimensions on a per dimension basis
* @param {boolean} [options.copy=false] - boolean indicating whether to copy source data to a new data buffer
* @param {boolean} [options.flatten=true] - boolean indicating whether to automatically flatten generic array data sources
* @param {NonNegativeInteger} [options.ndmin=0] - minimum number of dimensions
* @param {string} [options.casting="safe"] - casting rule used to determine what constitutes an acceptable cast
* @throws {TypeError} options argument must be an object
* @throws {TypeError} must provide valid options
* @throws {Error} must provide either an array shape, data source, or both
* @throws {Error} invalid cast
* @throws {RangeError} data source must be compatible with specified meta data
* @returns {ndarray} ndarray instance
*
* @example
* var arr = array( [ [ 1, 2 ], [ 3, 4 ] ] );
* // returns <ndarray>
*
* var v = arr.get( 0, 0 );
* // returns 1
*
* @example
* var opts = {
*     'dtype': 'generic',
*     'flatten': false
* };
*
* var arr = array( [ [ 1, 2 ], [ 3, 4 ] ], opts );
* // returns <ndarray>
*
* var v = arr.get( 0 );
* // returns [ 1, 2 ]
*
* @example
* var Float64Array = require( '@stdlib/array/float64' );
*
* var opts = {
*     'shape': [ 2, 2 ]
* };
*
* var arr = array( new Float64Array( [ 1.0, 2.0, 3.0, 4.0 ] ), opts );
* // returns <ndarray>
*
* var v = arr.get( 0, 0 );
* // returns 1.0
*/
function array() {
	var ndarray;
	var options;
	var strides;
	var buffer;
	var offset;
	var order;
	var dtype;
	var btype;
	var shape;
	var ndims;
	var nopts;
	var opts;
	var len;
	var ord;
	var FLG;

	if ( arguments.length === 1 ) {
		if ( isArrayLikeObject( arguments[ 0 ] ) ) {
			buffer = arguments[ 0 ];
			options = {};
		} else {
			options = arguments[ 0 ];
			if ( !isObject( options ) ) {
				throw new TypeError( 'invalid argument. Must provide either a valid data source, options argument, or both. Value: `' + options + '`.' );
			}
			if ( hasOwnProp( options, 'buffer' ) ) {
				buffer = options.buffer;
				if ( !isArrayLikeObject( buffer ) ) { // weak test
					throw new TypeError( 'invalid option. `buffer` option must be an array-like object, typed-array-like, a Buffer, or an ndarray. Option: `' + buffer + '`.' );
				}
			}
		}
	} else {
		buffer = arguments[ 0 ];
		if ( !isArrayLikeObject( buffer ) ) { // weak test
			throw new TypeError( 'invalid option. Data source must be an array-like object, typed-array-like, a Buffer, or an ndarray. Value: `' + buffer + '`.' );
		}
		options = arguments[ 1 ];
		if ( !isObject( options ) ) {
			throw new TypeError( 'invalid argument. Options argument must be an object. Value: `' + options + '`.' );
		}
		// Note: we ignore whether `options` has a `buffer` property
	}
	if ( buffer ) {
		if ( isndarrayLike( buffer ) ) {
			btype = buffer.dtype;
			FLG = true;
		} else {
			btype = getType( buffer );
			FLG = false;
		}
	}
	nopts = {};
	opts = {};

	// Validate some options before others...
	if ( hasOwnProp( options, 'casting' ) ) {
		opts.casting = options.casting;
		if ( !isCastingMode( opts.casting ) ) {
			throw new TypeError( 'invalid option. `casting` option must be a recognized casting mode. Option: `' + opts.casting + '`.' );
		}
	} else {
		opts.casting = defaults.casting;
	}
	if ( hasOwnProp( options, 'flatten' ) ) {
		opts.flatten = options.flatten;
		if ( !isBoolean( opts.flatten ) ) {
			throw new TypeError( 'invalid option. `flatten` option must be a boolean. Option: `' + opts.flatten + '`.' );
		}
	} else {
		opts.flatten = defaults.flatten;
	}
	if ( hasOwnProp( options, 'ndmin' ) ) {
		opts.ndmin = options.ndmin;
		if ( !isNonNegativeInteger( opts.ndmin ) ) {
			throw new TypeError( 'invalid option. `ndmin` option must be a nonnegative integer. Option: `' + opts.ndmin + '`.' );
		}
		// TODO: validate that minimum number of dimensions does not exceed the maximum number of possible dimensions (in theory, infinite; in practice, determined by max array length; see https://github.com/stdlib-js/stdlib/blob/ac350059877c036640775d6b30d0e98e840d07cf/lib/node_modules/%40stdlib/ndarray/ctor/lib/main.js#L57)
	} else {
		opts.ndmin = defaults.ndmin;
	}

	// Validate the remaining options...
	if ( hasOwnProp( options, 'dtype' ) ) {
		dtype = options.dtype;
		if ( !isDataType( dtype ) ) {
			throw new TypeError( 'invalid option. `dtype` option must be a recognized data type. Option: `' + dtype + '`.' );
		}
		if ( btype && !isAllowedCast( btype, dtype, opts.casting ) ) {
			throw new Error( 'invalid option. Data type cast is not allowed. Casting mode: `' + opts.casting + '`. From: `' + btype + '`. To: `' + dtype + '`.' );
		}
	} else if ( btype ) {
		// TODO: reconcile difference in behavior when provided a generic array and no `dtype` option. Currently, we cast here, but do not allow casting a generic array (by default) when explicitly providing a `dtype` option.

		// Only cast generic array data sources when not provided an ndarray...
		if ( !FLG && btype === 'generic' ) {
			dtype = defaults.dtype;
		} else {
			dtype = btype;
		}
	} else {
		dtype = defaults.dtype;
	}
	if ( hasOwnProp( options, 'order' ) ) {
		order = options.order;
		if ( order === 'any' || order === 'same' ) {
			if ( FLG ) {
				// If the user indicated that "any" order suffices (meaning the user does not care about ndarray order), then we use the default order, unless the input ndarray is either unequivocally "row-major" or "column-major" or configured as such....
				if ( order === 'any' ) {
					// Compute the layout order in order to ascertain whether an ndarray can be considered both "row-major" and "column-major":
					ord = strides2order( buffer.strides );

					// If the ndarray can be considered both "row-major" and "column-major", then use the default order; otherwise, use the ndarray's stated layout order...
					if ( ord === 'both' ) {
						order = defaults.order;
					} else {
						order = buffer.order;
					}
				}
				// Otherwise, use the same order as the provided ndarray...
				else if ( order === 'same' ) {
					order = buffer.order;
				}
			} else {
				order = defaults.order;
			}
		} else if ( !isOrder( order ) ) {
			throw new TypeError( 'invalid option. `order` option must be a recognized order. Option: `' + order + '`.' );
		}
	} else {
		order = defaults.order;
	}
	if ( hasOwnProp( options, 'codegen' ) ) {
		nopts.codegen = options.codegen;
	} else {
		nopts.codegen = defaults.codegen;
	}
	if ( hasOwnProp( options, 'mode' ) ) {
		nopts.mode = options.mode;
	} else {
		nopts.mode = defaults.mode;
	}
	if ( hasOwnProp( options, 'submode' ) ) {
		nopts.submode = options.submode;
	} else {
		nopts.submode = [ nopts.mode ];
	}
	if ( hasOwnProp( options, 'copy' ) ) {
		opts.copy = options.copy;
		if ( !isBoolean( opts.copy ) ) {
			throw new TypeError( 'invalid option. `copy` option must be a boolean. Option: `' + opts.copy + '`.' );
		}
	} else {
		opts.copy = defaults.copy;
	}
	// If not provided a shape, infer from a provided data source...
	if ( hasOwnProp( options, 'shape' ) ) {
		shape = options.shape;
		if ( !isArrayLikeObject( shape ) ) { // weak test
			throw new TypeError( 'invalid option. `shape` option must be an array-like object containing nonnegative integers. Option: `' + shape + '`.' );
		}
		ndims = shape.length;
		len = numel( shape );
	} else if ( buffer ) {
		if ( FLG ) {
			shape = buffer.shape;
			ndims = buffer.ndims;
			len = buffer.length;
		} else if ( opts.flatten && isArray( buffer ) ) {
			shape = arrayShape( buffer );
			ndims = shape.length;
			len = numel( shape );
		} else {
			ndims = 1;
			len = buffer.length;
			shape = [ len ]; // assume a 1-dimensional array (vector)
		}
	} else {
		throw new Error( 'invalid arguments. Must provide either a data source, array shape, or both.' );
	}
	// Adjust the array shape to satisfy the minimum number of dimensions...
	if ( ndims < opts.ndmin ) {
		shape = expandShape( ndims, shape, opts.ndmin );
		ndims = opts.ndmin;
	}
	// If not provided a data buffer, create it; otherwise, see if we need to cast a provided data buffer to another data type or perform a copy...
	if ( FLG ) {
		if ( buffer.length !== len ) {
			throw new RangeError( 'invalid arguments. Array shape is incompatible with provided data source. Number of data source elements does not match array shape.' );
		}
		if ( btype !== dtype || opts.copy ) {
			buffer = copyView( buffer, dtype );
		} else {
			strides = buffer.strides;
			offset = buffer.offset;
			buffer = buffer.data;
			if ( strides.length < ndims ) {
				// Account for augmented dimensions (note: expanding the strides array to account for prepended singleton dimensions does **not** affect the index offset):
				strides = expandStrides( ndims, shape, strides, order );
			}
		}
	} else if ( buffer ) {
		if ( btype === 'generic' && opts.flatten ) {
			buffer = flattenArray( buffer );
		}
		if ( buffer.length !== len ) {
			throw new RangeError( 'invalid arguments. Array shape is incompatible with provided data source. Number of data source elements does not match array shape.' );
		}
		if ( btype !== dtype || opts.copy ) {
			buffer = castBuffer( buffer, len, dtype );
		}
	} else {
		buffer = createBuffer( dtype, len );
	}
	// If we have yet to determine array strides, we assume that we can compute the strides, along with the index offset, for a **contiguous** data source based solely on the array shape and specified memory layout order...
	if ( strides === void 0 ) {
		strides = shape2strides( shape, order );
		offset = strides2offset( shape, strides );
	}
	// Use a heuristic to avoid memoization of highly-specialized ndarray constructors, thus effectively introducing "fast" and "slow" ndarray construction paths...
	if ( nopts.submode.length < 3 ) {
		ndarray = mctor( dtype, ndims, nopts );
		return new ndarray( buffer, shape, strides, offset, order );
	}
	ndarray = ctor( dtype, ndims, nopts );
	return new ndarray( buffer, shape, strides, offset, order );
}

// EXPORTS //

module.exports = array;
<|endoftext|>


<commit_before>import React from 'react'
import { Link } from 'react-router'
import UserContainer from '../containers/user_container'

class Header extends React.Component {
  render() {
    return(

<Link to='/' onlyActiveOnIndex>Fix It</Link>

            0

<Link activeClassName="active" to="leaderboard">
                  <svg className='nav-icon' viewBox="0 0 200 200">
                    <title>Leader Board</title>
                    <rect x="11.4" y="56" width="24" height="144"/>
                    <rect x="113.5" y="40" width="24" height="160"/>
                    <rect x="62.4" y="0" width="24" height="200"/>
                    <rect x="164.6" y="80" width="24" height="120"/>
                  </svg>
                </Link>

<Link activeClassName="active" to="/" onlyActiveOnIndex>
                  <svg className='nav-icon' viewBox="0 0 200 200">
                    <title>Game Menu</title>
                    <path d="M100.5 60.9c14.4 0 26.1-11.7 26.1-26.1 0-14.4-11.7-26.1-26.1-26.1S74.4 20.4 74.4 34.8c0 14.4 11.7 26.1 26.1 26.1"/>
                    <path d="M100.5 63.6c-15.8 0-28.7-12.9-28.7-28.7 0-15.8 12.9-28.7 28.7-28.7 15.8 0 28.7 12.9 28.7 28.7 0 15.8-12.9 28.7-28.7 28.7zm0-52.2c-12.9 0-23.4 10.5-23.4 23.4 0 12.9 10.5 23.4 23.4 23.4s23.4-10.5 23.4-23.4c0-12.9-10.5-23.4-23.4-23.4zM28.5 190.2c14.4 0 26.1-11.7 26.1-26.1 0-14.4-11.7-26.1-26.1-26.1S2.4 149.7 2.4 164.1c0 14.4 11.7 26.1 26.1 26.1"/>
                    <path d="M28.5 192.8c-15.8 0-28.7-12.9-28.7-28.7s12.9-28.7 28.7-28.7c15.8 0 28.7 12.9 28.7 28.7s-12.9 28.7-28.7 28.7zm0-52.1c-12.9 0-23.4 10.5-23.4 23.4 0 12.9 10.5 23.4 23.4 23.4s23.4-10.5 23.4-23.4c0-12.9-10.5-23.4-23.4-23.4zM171.1 190.2c14.4 0 26.1-11.7 26.1-26.1 0-14.4-11.7-26.1-26.1-26.1-14.4 0-26.1 11.7-26.1 26.1 0 14.4 11.7 26.1 26.1 26.1"/>
                    <path d="M171.1 192.8c-15.8 0-28.7-12.9-28.7-28.7s12.9-28.7 28.7-28.7c15.8 0 28.7 12.9 28.7 28.7s-12.9 28.7-28.7 28.7zm0-52.1c-12.9 0-23.4 10.5-23.4 23.4 0 12.9 10.5 23.4 23.4 23.4s23.4-10.5 23.4-23.4c0-12.9-10.5-23.4-23.4-23.4zM70.3 160.9h59.9v16H70.3zM131.076 68.195l29.95 51.873-13.856 8-29.95-51.873zM73.24 68.215l13.857 8L57.14 128.09l-13.855-8.002z"/>
                  </svg>
                </Link>

<Link activeClassName="active" to="settings">
                <svg className="nav-icon" viewBox="0 0 200 200">
                  <title>Settings</title>
                  <path d="M134.6,115.1c5-4.6,9.4-10.2,12.8-16.5c5.5-10.2,8.4-22,8.4-34.2c0-16.9-5.6-32.8-15.6-44.9 C129.7,6.9,115.6,0,100.4,0S71.1,6.9,60.6,19.5c-10.1,12.1-15.6,28-15.6,44.9c0,12.1,2.9,24,8.4,34.2c3.4,6.4,7.8,12,12.8,16.5 c-11.4,5.5-22,14.9-30.7,27.5c-10.3,15-16.5,32.6-16.5,47.2c0,5.6,4.6,10.2,10.2,10.2h142.4c5.6,0,10.2-4.6,10.2-10.2 c0-14.6-6.2-32.2-16.5-47.2C156.7,130.1,146.1,120.6,134.6,115.1z M40.7,179.7c2-8.3,6-17.5,11.6-25.5 c8.8-12.8,19.7-21.1,30.9-23.5c4.7-1,8-5.1,8-9.9v-7.3c0-3.7-2-7-5.1-8.8c-12.6-7.2-20.7-22.9-20.7-40.2 c0-24.3,15.8-44.1,35.1-44.1s35.1,19.8,35.1,44.1c0,17.2-8.1,33-20.7,40.2c-3.2,1.8-5.1,5.2-5.1,8.8v7.3c0,4.8,3.3,8.9,8,9.9 c11.1,2.4,22.1,10.7,30.9,23.5c5.6,8.1,9.6,17.2,11.6,25.5H40.7z"/>
                </svg>
                </Link>

          {React.cloneElement(this.props.children, this.props)}

    )
  }
}

export default Header;<commit_msg>addition of transition group for score in the header and hooked up score to store<commit_after>import React from 'react'
import { Link } from 'react-router'
import UserContainer from '../containers/user_container'
import ReactCSSTransitionGroup from 'react-addons-css-transition-group'

class Header extends React.Component {
  render() {
    return(

<Link to='/' onlyActiveOnIndex>Fix It</Link>

            <ReactCSSTransitionGroup
              component="span"
              className="score delta"
              transitionName="score"
              transitionEnterTimeout={250}
              transitionLeaveTimeout={250}
            >
            {this.props.score.totalScore}
            </ReactCSSTransitionGroup>

<Link activeClassName="active" to="leaderboard">
                  <svg className='nav-icon' viewBox="0 0 200 200">
                    <title>Leader Board</title>
                    <rect x="11.4" y="56" width="24" height="144"/>
                    <rect x="113.5" y="40" width="24" height="160"/>
                    <rect x="62.4" y="0" width="24" height="200"/>
                    <rect x="164.6" y="80" width="24" height="120"/>
                  </svg>
                </Link>

<Link activeClassName="active" to="/" onlyActiveOnIndex>
                  <svg className='nav-icon' viewBox="0 0 200 200">
                    <title>Game Menu</title>
                    <path d="M100.5 60.9c14.4 0 26.1-11.7 26.1-26.1 0-14.4-11.7-26.1-26.1-26.1S74.4 20.4 74.4 34.8c0 14.4 11.7 26.1 26.1 26.1"/>
                    <path d="M100.5 63.6c-15.8 0-28.7-12.9-28.7-28.7 0-15.8 12.9-28.7 28.7-28.7 15.8 0 28.7 12.9 28.7 28.7 0 15.8-12.9 28.7-28.7 28.7zm0-52.2c-12.9 0-23.4 10.5-23.4 23.4 0 12.9 10.5 23.4 23.4 23.4s23.4-10.5 23.4-23.4c0-12.9-10.5-23.4-23.4-23.4zM28.5 190.2c14.4 0 26.1-11.7 26.1-26.1 0-14.4-11.7-26.1-26.1-26.1S2.4 149.7 2.4 164.1c0 14.4 11.7 26.1 26.1 26.1"/>
                    <path d="M28.5 192.8c-15.8 0-28.7-12.9-28.7-28.7s12.9-28.7 28.7-28.7c15.8 0 28.7 12.9 28.7 28.7s-12.9 28.7-28.7 28.7zm0-52.1c-12.9 0-23.4 10.5-23.4 23.4 0 12.9 10.5 23.4 23.4 23.4s23.4-10.5 23.4-23.4c0-12.9-10.5-23.4-23.4-23.4zM171.1 190.2c14.4 0 26.1-11.7 26.1-26.1 0-14.4-11.7-26.1-26.1-26.1-14.4 0-26.1 11.7-26.1 26.1 0 14.4 11.7 26.1 26.1 26.1"/>
                    <path d="M171.1 192.8c-15.8 0-28.7-12.9-28.7-28.7s12.9-28.7 28.7-28.7c15.8 0 28.7 12.9 28.7 28.7s-12.9 28.7-28.7 28.7zm0-52.1c-12.9 0-23.4 10.5-23.4 23.4 0 12.9 10.5 23.4 23.4 23.4s23.4-10.5 23.4-23.4c0-12.9-10.5-23.4-23.4-23.4zM70.3 160.9h59.9v16H70.3zM131.076 68.195l29.95 51.873-13.856 8-29.95-51.873zM73.24 68.215l13.857 8L57.14 128.09l-13.855-8.002z"/>
                  </svg>
                </Link>

<Link activeClassName="active" to="settings">
                <svg className="nav-icon" viewBox="0 0 200 200">
                  <title>Settings</title>
                  <path d="M134.6,115.1c5-4.6,9.4-10.2,12.8-16.5c5.5-10.2,8.4-22,8.4-34.2c0-16.9-5.6-32.8-15.6-44.9 C129.7,6.9,115.6,0,100.4,0S71.1,6.9,60.6,19.5c-10.1,12.1-15.6,28-15.6,44.9c0,12.1,2.9,24,8.4,34.2c3.4,6.4,7.8,12,12.8,16.5 c-11.4,5.5-22,14.9-30.7,27.5c-10.3,15-16.5,32.6-16.5,47.2c0,5.6,4.6,10.2,10.2,10.2h142.4c5.6,0,10.2-4.6,10.2-10.2 c0-14.6-6.2-32.2-16.5-47.2C156.7,130.1,146.1,120.6,134.6,115.1z M40.7,179.7c2-8.3,6-17.5,11.6-25.5 c8.8-12.8,19.7-21.1,30.9-23.5c4.7-1,8-5.1,8-9.9v-7.3c0-3.7-2-7-5.1-8.8c-12.6-7.2-20.7-22.9-20.7-40.2 c0-24.3,15.8-44.1,35.1-44.1s35.1,19.8,35.1,44.1c0,17.2-8.1,33-20.7,40.2c-3.2,1.8-5.1,5.2-5.1,8.8v7.3c0,4.8,3.3,8.9,8,9.9 c11.1,2.4,22.1,10.7,30.9,23.5c5.6,8.1,9.6,17.2,11.6,25.5H40.7z"/>
                </svg>
                </Link>

          {React.cloneElement(this.props.children, this.props)}

    )
  }
}

export default Header;<|endoftext|>


<commit_before>!function(e,n){"object"==typeof exports?module.exports=n():"function"==typeof define&&define.amd?define(n):e.crel=n()}(this,function(){function e(){var o,a=arguments,p=a[0],m=a[1],x=2,v=a.length,b=e[f];if(p=e[c](p)?p:d.createElement(p),1===v)return p;if((!l(m,t)||e[u](m)||s(m))&&(--x,m=null),v-x===1&&l(a[x],"string")&&void 0!==p[r])p[r]=a[x];else for(;v>x;++x)if(o=a[x],null!=o)if(s(o))for(var g=0;g<o.length;++g)y(p,o[g]);else y(p,o);for(var h in m)if(b[h]){var N=b[h];typeof N===n?N(p,m[h]):p[i](N,m[h])}else p[i](h,m[h]);return p}var n="function",t="object",o="nodeType",r="textContent",i="setAttribute",f="attrMap",u="isNode",c="isElement",d=typeof document===t?document:{},l=function(e,n){return typeof e===n},a=typeof Node===n?function(e){return e instanceof Node}:function(e){return e&&l(e,t)&&o in e&&l(e.ownerDocument,t)},p=function(n){return e[u](n)&&1===n[o]},s=function(e){return e instanceof Array},y=function(n,t){e[u](t)||(t=d.createTextNode(t)),n.appendChild(t)};return e[f]={},e[c]=p,e[u]=a,"undefined"!=typeof Proxy&&(e.proxy=new Proxy(e,{get:function(n,t){return!(t in e)&&(e[t]=e.bind(null,t)),e[t]}})),e});
<commit_msg>Rebuild crel.min<commit_after>!function(e,n){"object"==typeof exports?module.exports=n():"function"==typeof define&&define.amd?define(n):e.crel=n()}(this,function(){function e(){var a,d=arguments,s=d[0],p=d[1],y=2,x=d.length,m=e[o];if(s=e[u](s)?s:c.createElement(s),x>1){if((!n(p,r)||e[f](p)||Array.isArray(p))&&(--y,p=null),x-y==1&&n(d[y],"string"))s.textContent=d[y];else for(;y<x;++y)null!==(a=d[y])&&l(s,a);for(var v in p)if(m[v]){var A=m[v];n(A,t)?A(s,p[v]):s[i](A,p[v])}else n(p[v],t)?s[v]=p[v]:s[i](v,p[v])}return s}var n=function(e,n){return typeof e===n},t="function",r="object",i="setAttribute",o="attrMap",f="isNode",u="isElement",c=document,a=function(e){return e instanceof Node},d=function(n){return e[f](n)&&1===n.nodeType},l=function(n,t){if(Array.isArray(t))return void t.map(function(e){l(n,e)});e[f](t)||(t=c.createTextNode(t)),n.appendChild(t)};return e[o]={},e[u]=d,e[f]=a,n(Proxy,"undefined")||(e.proxy=new Proxy(e,{get:function(n,t){return!(t in e)&&(e[t]=e.bind(null,t)),e[t]}})),e});
<|endoftext|>


<commit_before>/*
Copyright (c) 2016, Geomatics and Cartographic Research Centre, Carleton
University
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 - Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.
 - Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.
 - Neither the name of the Geomatics and Cartographic Research Centre,
   Carleton University nor the names of its contributors may be used to
   endorse or promote products derived from this software without specific
   prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

;(function($,$n2) {
"use strict";

var
 _loc = function(str,args){ return $n2.loc(str,'nunaliit2',args); }
 ,DH = 'n2.utilities'
 ;

//--------------------------------------------------------------------------
var AssignLayerOnDocumentCreation = $n2.Class({

	layerId: null,

	onlyWithGeometries: null,

	dispatchService: null,

	initialize: function(opts_){
		var opts = $n2.extend({
			layerId: null
			,onlyWithGeometries: false
			,dispatchService: null
		},opts_);

		var _this = this;

		this.layerId = opts.layerId;
		this.onlyWithGeometries = opts.onlyWithGeometries;
		this.dispatchService = opts.dispatchService;

		// Register to events
		if( this.dispatchService ){
			var f = function(m, addr, dispatcher){
				_this._handle(m, addr, dispatcher);
			};

			this.dispatchService.register(DH,'preDocCreation',f);
		};

		$n2.log('AssignLayerOnDocumentCreation', this);
	},

	_handle: function(m, addr, dispatcher){
		if( 'preDocCreation' === m.type ){
			var createdDoc = m.doc;

			var addLayer = true;
			if( this.onlyWithGeometries ){
				if( createdDoc.nunaliit_geom ){

				} else {
					addLayer = false;
				};
			};

			if( addLayer ){
				if( !createdDoc.nunaliit_layers ){
					createdDoc.nunaliit_layers = [];
				};

				if( this.layerId ){
					if( createdDoc.nunaliit_layers.indexOf(this.layerId) < 0 ){
						createdDoc.nunaliit_layers.push(this.layerId);
					};
				};
			};
		};
	}
});

//--------------------------------------------------------------------------
var SelectDocumentOnModuleIntroduction = $n2.Class({

	docIds: null,

	dispatchService: null,

	initialize: function(opts_){
		var opts = $n2.extend({
			docId: null
			,docIds: null
			,dispatchService: null
		},opts_);

		var _this = this;

		this.dispatchService = opts.dispatchService;
		this.docIds = [];

		this.moduleStarted = false;

		if( typeof opts.docId === 'string' ){
			this.docIds.push(opts.docId);
		};
		if( $n2.isArray(opts.docIds) ){
			for(var i=0,e=opts.docIds.length; i<e; ++i){
				var docId = opts.docIds[i];
				if( typeof docId === 'string' ){
					this.docIds.push(docId);
				};
			};
		};

		// Register to events
		if( this.dispatchService ){
			var f = function(m, addr, dispatcher){
				_this._handle(m, addr, dispatcher);
			};

			this.dispatchService.register(DH,'modulePerformIntroduction',f);
		};

		$n2.log('SelectDocumentOnModuleIntroduction', this);
	},

	_handle: function(m, addr, dispatcher){
		if( 'modulePerformIntroduction' === m.type ){
			if( !m.performed ){
				if( this.docIds.length > 1 ){
					m.performed = true;
					this.dispatchService.send(DH,{
						type: 'selected'
						,docIds: this.docIds
					});

				} else if( this.docIds.length > 0 ){
					m.performed = true;
					this.dispatchService.send(DH,{
						type: 'selected'
						,docId: this.docIds[0]
					});
				};
			};
		};
	}
});

//--------------------------------------------------------------------------
// This utility performs a document selection when the current selection on a filter
// is changed. In this case, a filter refers to a document model of type
// SelectableDocumentFilter. This utility is configured with a map of choices pointing
// to a document identifier. If the choices match, then the utility sends a
// selection on the associated document.
// The selection map is structured in such a way that the key is the identifier
// of the document to be selected. The values in the map can be a string or an
// array of strings. These are the choices selected in the associated filter
// model.
// For example:
// {
//     "utilityType": "selectDocumentOnFilterChange"
//     ,"sourceModelId": "filterDocsByLayer"
//     ,"performSelectedEvent": false
//     ,"selectionMap": {
//    	  "123": "public"
//    	  ,"456": "approved"
//    	  ,"789": [ "public", "approved" ]
//     }
// }
var SelectDocumentOnFilterChange = $n2.Class('SelectDocumentOnFilterChange',{

	dispatchService: null,

	sourceModelId: null,

	selectionToDocId: null,

	/**
	 * Name of event used by source model to report changes in choices
	 */
	selectedChoicesChangeEventName: null,

	/**
	 * If set, send a 'selected' event instead of a 'userSelect' event.
	 */
	performSelectedEvent: null,

	initialize: function(opts_){
		var opts = $n2.extend({
			dispatchService: undefined
			,sourceModelId: undefined
			,selectionMap: undefined
			,performSelectedEvent: undefined
		},opts_);

		var _this = this;

		this.dispatchService = opts.dispatchService;

		if( typeof opts.sourceModelId === 'string' ){
			this.sourceModelId = opts.sourceModelId;
		} else {
			throw new Error('In configuration for SelectDocumentOnFilterChange, sourceModelId must be specified as a string');
		};

		this.selectionToDocId = {};
		if( opts.selectionMap && typeof opts.selectionMap === 'object' ){
			for(var docId in opts.selectionMap){
				var selection = opts.selectionMap[docId];
				var selectionString = this._selectionToString(selection);
				if( selectionString ){
					this.selectionToDocId[selectionString] = docId;
				};
			};
		};

		this.performSelectedEvent = false;
		if( opts.performSelectedEvent ){
			this.performSelectedEvent = true;
		};

		// Register to events
		if( this.dispatchService && this.sourceModelId ){
			var fn = function(m, addr, dispatcher){
				_this._handleFilterChange(m, addr, dispatcher);
			};

			// Get model info
			var modelInfoRequest = {
				type: 'modelGetInfo'
				,modelId: this.sourceModelId
				,modelInfo: null
			};
			this.dispatchService.synchronousCall(DH, modelInfoRequest);
			var sourceModelInfo = modelInfoRequest.modelInfo;

			if( sourceModelInfo
			 && sourceModelInfo.parameters
			 && sourceModelInfo.parameters.selectedChoices ){
				var paramInfo = sourceModelInfo.parameters.selectedChoices;
				this.selectedChoicesChangeEventName = paramInfo.changeEvent;
			};

			if( this.selectedChoicesChangeEventName ){
				this.dispatchService.register(DH, this.selectedChoicesChangeEventName, fn);
			};
		};

		$n2.log(this._classname, this);
	},

	_handleFilterChange: function(m, addr, dispatcher){
		if( this.selectedChoicesChangeEventName === m.type ){
			if( m.value ){
				var selection = m.value;
				var selectionString = this._selectionToString(selection);
				var docId = this.selectionToDocId[selectionString];
				if( docId ){
					var eventType = 'userSelect';
					if( this.performSelectedEvent ){
						eventType = 'selected';
					};

					this.dispatchService.send(DH, {
						type: eventType
						,docId: docId
					});
				};
			};
		};
	},

	/**
	 * Turns an array of selectors into a single string. First, sorts
	 * the items in array. Then, escapes each string. Finally, concatenate
	 * each string using a separator.
	 *
	 * 'abc' -> 'abc'
	 * [ 'def', 'abc' ] -> 'abc|def'
	 * [ 'a|b', 'c|d' ] -> 'a||b|c||d'
	 */
	_selectionToString: function(selection){
		var _this = this;

		var selectionString = undefined;

		if( typeof selection === 'string' ){
			selectionString = this._escapeSelector(selection);

		} else if( $n2.isArray(selection) ){
			var effectiveSelection = [];
			selection.forEach(function(sel){
				if( typeof sel === 'string' ){
					effectiveSelection.push( _this._escapeSelector(sel) );
				};
			});

			effectiveSelection.sort();

			selectionString = effectiveSelection.join('|');
		};

		return selectionString;
	},

	_escapeSelector: function(sel){
		return sel.replace(/\|/g, 'oranges');
	}
});

//--------------------------------------------------------------------------
var Service = $n2.Class({

	dispatchService: null,

	initialize: function(opts_){
		var opts = $n2.extend({
			dispatchService: null
		},opts_);

		var _this = this;

		this.dispatchService = opts.dispatchService;

		// Register to events
		if( this.dispatchService ){
			var f = function(m, addr, dispatcher){
				_this._handle(m, addr, dispatcher);
			};
			this.dispatchService.register(DH,'utilityCreate',f);
		};
	},

	_handle: function(m, addr, dispatcher){
		if( 'utilityCreate' === m.type ){
			if( ! m.utilityType ){
				$n2.log('utilityType must be provided when creating a utility');
				return;
			};

			if( 'assignLayerOnDocumentCreation' === m.utilityType ){
				var options = {};

				if( typeof m.utilityOptions === 'object' ){
					for(var key in m.utilityOptions){
						var value = m.utilityOptions[key];
						options[key] = value;
					};
				};

				if( m.config ){
					if( m.config.directory ){
						options.dispatchService = m.config.directory.dispatchService;
					};
				};

		        new AssignLayerOnDocumentCreation(options);

		        m.created = true;

			} else if( 'selectDocumentOnModuleIntroduction' === m.utilityType ){
				var options = {};

				if( typeof m.utilityOptions === 'object' ){
					for(var key in m.utilityOptions){
						var value = m.utilityOptions[key];
						options[key] = value;
					};
				};

				if( m.config ){
					if( m.config.directory ){
						options.dispatchService = m.config.directory.dispatchService;
					};
				};

		        new SelectDocumentOnModuleIntroduction(options);

		        m.created = true;

			} else if( 'selectDocumentOnFilterChange' === m.utilityType ){
				var options = {};

				if( typeof m.utilityOptions === 'object' ){
					for(var key in m.utilityOptions){
						var value = m.utilityOptions[key];
						options[key] = value;
					};
				};

				if( m.config ){
					if( m.config.directory ){
						options.dispatchService = m.config.directory.dispatchService;
					};
				};

		        new SelectDocumentOnFilterChange(options);

		        m.created = true;

			} else {
				if( $n2.mapUtilities
				 && typeof $n2.mapUtilities.HandleUtilityCreateRequests === 'function' ){
					$n2.mapUtilities.HandleUtilityCreateRequests(m, addr, dispatcher);
				};

				if( $n2.utilitiesModel
				 && typeof $n2.utilitiesModel.HandleUtilityCreateRequests === 'function' ){
					$n2.utilitiesModel.HandleUtilityCreateRequests(m, addr, dispatcher);
				};

				if( $n2.utilitiesChangeDetectors
					&& typeof $n2.utilitiesChangeDetectors.HandleUtilityCreateRequests === 'function' ){
					$n2.utilitiesChangeDetectors.HandleUtilityCreateRequests(m, addr, dispatcher);
				};
		    };
		};
	}
});

//--------------------------------------------------------------------------
$n2.utilities = {
	Service: Service
	,AssignLayerOnDocumentCreation: AssignLayerOnDocumentCreation
	,SelectDocumentOnModuleIntroduction: SelectDocumentOnModuleIntroduction
	,SelectDocumentOnFilterChange: SelectDocumentOnFilterChange
};

})(jQuery,nunaliit2);
<commit_msg>Utility AssignLayerOnDocumentCreation: Add more than one layer on creation (#1072)<commit_after>/*
Copyright (c) 2016, Geomatics and Cartographic Research Centre, Carleton
University
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 - Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.
 - Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.
 - Neither the name of the Geomatics and Cartographic Research Centre,
   Carleton University nor the names of its contributors may be used to
   endorse or promote products derived from this software without specific
   prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

;(function($,$n2) {
"use strict";

var
 _loc = function(str,args){ return $n2.loc(str,'nunaliit2',args); }
 ,DH = 'n2.utilities'
 ;

//--------------------------------------------------------------------------
	const AssignLayerOnDocumentCreation = $n2.Class({
		layerId: null,
		onlyWithGeometries: null,
		dispatchService: null,

		initialize: function (opts_) {
			const opts = $n2.extend({
				layerId: null
				, onlyWithGeometries: false
				, dispatchService: null
			}, opts_);

			const _this = this;

			this.layerId = opts.layerId;
			this.onlyWithGeometries = opts.onlyWithGeometries;
			this.dispatchService = opts.dispatchService;

			const isArrayOfLayers = Array.isArray(this.layerId);
			if (typeof this.layerId !== "string" && !isArrayOfLayers) {
				throw new Error("Utility AssignLayerOnDocumentCreation's layerId must be a string or an array of strings");
			}
			if (isArrayOfLayers) {
				if (!this.layerId.every(layer => typeof layer === "string")) {
					throw new Error("Utility AssignLayerOnDocumentCreation's layerId contains a value that is not a string");
				}
			}

			// Register to events
			if (this.dispatchService) {
				const f = function (m, addr, dispatcher) {
					_this._handle(m, addr, dispatcher);
				};
				this.dispatchService.register(DH, 'preDocCreation', f);
			}

			$n2.log('AssignLayerOnDocumentCreation', this);
		},

		_handle: function (m, addr, dispatcher) {
			if ('preDocCreation' === m.type) {
				const createdDoc = m.doc;
				let addLayer = true;

				if (this.onlyWithGeometries) {
					if (!createdDoc.hasOwnProperty("nunaliit_geom")) {
						addLayer = false;
					}
				}

				if (addLayer) {
					if (!createdDoc.nunaliit_layers) {
						createdDoc.nunaliit_layers = [];
					}

					if (this.layerId) {
						let layers = this.layerId;
						if (typeof layers === "string") layers = [layers];
						createdDoc.nunaliit_layers = [...new Set(
							[...createdDoc.nunaliit_layers, ...layers]
						)];
					}
				}
			}
		}
	});

//--------------------------------------------------------------------------
var SelectDocumentOnModuleIntroduction = $n2.Class({

	docIds: null,

	dispatchService: null,

	initialize: function(opts_){
		var opts = $n2.extend({
			docId: null
			,docIds: null
			,dispatchService: null
		},opts_);

		var _this = this;

		this.dispatchService = opts.dispatchService;
		this.docIds = [];

		this.moduleStarted = false;

		if( typeof opts.docId === 'string' ){
			this.docIds.push(opts.docId);
		};
		if( $n2.isArray(opts.docIds) ){
			for(var i=0,e=opts.docIds.length; i<e; ++i){
				var docId = opts.docIds[i];
				if( typeof docId === 'string' ){
					this.docIds.push(docId);
				};
			};
		};

		// Register to events
		if( this.dispatchService ){
			var f = function(m, addr, dispatcher){
				_this._handle(m, addr, dispatcher);
			};

			this.dispatchService.register(DH,'modulePerformIntroduction',f);
		};

		$n2.log('SelectDocumentOnModuleIntroduction', this);
	},

	_handle: function(m, addr, dispatcher){
		if( 'modulePerformIntroduction' === m.type ){
			if( !m.performed ){
				if( this.docIds.length > 1 ){
					m.performed = true;
					this.dispatchService.send(DH,{
						type: 'selected'
						,docIds: this.docIds
					});

				} else if( this.docIds.length > 0 ){
					m.performed = true;
					this.dispatchService.send(DH,{
						type: 'selected'
						,docId: this.docIds[0]
					});
				};
			};
		};
	}
});

//--------------------------------------------------------------------------
// This utility performs a document selection when the current selection on a filter
// is changed. In this case, a filter refers to a document model of type
// SelectableDocumentFilter. This utility is configured with a map of choices pointing
// to a document identifier. If the choices match, then the utility sends a
// selection on the associated document.
// The selection map is structured in such a way that the key is the identifier
// of the document to be selected. The values in the map can be a string or an
// array of strings. These are the choices selected in the associated filter
// model.
// For example:
// {
//     "utilityType": "selectDocumentOnFilterChange"
//     ,"sourceModelId": "filterDocsByLayer"
//     ,"performSelectedEvent": false
//     ,"selectionMap": {
//    	  "123": "public"
//    	  ,"456": "approved"
//    	  ,"789": [ "public", "approved" ]
//     }
// }
var SelectDocumentOnFilterChange = $n2.Class('SelectDocumentOnFilterChange',{

	dispatchService: null,

	sourceModelId: null,

	selectionToDocId: null,

	/**
	 * Name of event used by source model to report changes in choices
	 */
	selectedChoicesChangeEventName: null,

	/**
	 * If set, send a 'selected' event instead of a 'userSelect' event.
	 */
	performSelectedEvent: null,

	initialize: function(opts_){
		var opts = $n2.extend({
			dispatchService: undefined
			,sourceModelId: undefined
			,selectionMap: undefined
			,performSelectedEvent: undefined
		},opts_);

		var _this = this;

		this.dispatchService = opts.dispatchService;

		if( typeof opts.sourceModelId === 'string' ){
			this.sourceModelId = opts.sourceModelId;
		} else {
			throw new Error('In configuration for SelectDocumentOnFilterChange, sourceModelId must be specified as a string');
		};

		this.selectionToDocId = {};
		if( opts.selectionMap && typeof opts.selectionMap === 'object' ){
			for(var docId in opts.selectionMap){
				var selection = opts.selectionMap[docId];
				var selectionString = this._selectionToString(selection);
				if( selectionString ){
					this.selectionToDocId[selectionString] = docId;
				};
			};
		};

		this.performSelectedEvent = false;
		if( opts.performSelectedEvent ){
			this.performSelectedEvent = true;
		};

		// Register to events
		if( this.dispatchService && this.sourceModelId ){
			var fn = function(m, addr, dispatcher){
				_this._handleFilterChange(m, addr, dispatcher);
			};

			// Get model info
			var modelInfoRequest = {
				type: 'modelGetInfo'
				,modelId: this.sourceModelId
				,modelInfo: null
			};
			this.dispatchService.synchronousCall(DH, modelInfoRequest);
			var sourceModelInfo = modelInfoRequest.modelInfo;

			if( sourceModelInfo
			 && sourceModelInfo.parameters
			 && sourceModelInfo.parameters.selectedChoices ){
				var paramInfo = sourceModelInfo.parameters.selectedChoices;
				this.selectedChoicesChangeEventName = paramInfo.changeEvent;
			};

			if( this.selectedChoicesChangeEventName ){
				this.dispatchService.register(DH, this.selectedChoicesChangeEventName, fn);
			};
		};

		$n2.log(this._classname, this);
	},

	_handleFilterChange: function(m, addr, dispatcher){
		if( this.selectedChoicesChangeEventName === m.type ){
			if( m.value ){
				var selection = m.value;
				var selectionString = this._selectionToString(selection);
				var docId = this.selectionToDocId[selectionString];
				if( docId ){
					var eventType = 'userSelect';
					if( this.performSelectedEvent ){
						eventType = 'selected';
					};

					this.dispatchService.send(DH, {
						type: eventType
						,docId: docId
					});
				};
			};
		};
	},

	/**
	 * Turns an array of selectors into a single string. First, sorts
	 * the items in array. Then, escapes each string. Finally, concatenate
	 * each string using a separator.
	 *
	 * 'abc' -> 'abc'
	 * [ 'def', 'abc' ] -> 'abc|def'
	 * [ 'a|b', 'c|d' ] -> 'a||b|c||d'
	 */
	_selectionToString: function(selection){
		var _this = this;

		var selectionString = undefined;

		if( typeof selection === 'string' ){
			selectionString = this._escapeSelector(selection);

		} else if( $n2.isArray(selection) ){
			var effectiveSelection = [];
			selection.forEach(function(sel){
				if( typeof sel === 'string' ){
					effectiveSelection.push( _this._escapeSelector(sel) );
				};
			});

			effectiveSelection.sort();

			selectionString = effectiveSelection.join('|');
		};

		return selectionString;
	},

	_escapeSelector: function(sel){
		return sel.replace(/\|/g, 'oranges');
	}
});

//--------------------------------------------------------------------------
var Service = $n2.Class({

	dispatchService: null,

	initialize: function(opts_){
		var opts = $n2.extend({
			dispatchService: null
		},opts_);

		var _this = this;

		this.dispatchService = opts.dispatchService;

		// Register to events
		if( this.dispatchService ){
			var f = function(m, addr, dispatcher){
				_this._handle(m, addr, dispatcher);
			};
			this.dispatchService.register(DH,'utilityCreate',f);
		};
	},

	_handle: function(m, addr, dispatcher){
		if( 'utilityCreate' === m.type ){
			if( ! m.utilityType ){
				$n2.log('utilityType must be provided when creating a utility');
				return;
			};

			if( 'assignLayerOnDocumentCreation' === m.utilityType ){
				var options = {};

				if( typeof m.utilityOptions === 'object' ){
					for(var key in m.utilityOptions){
						var value = m.utilityOptions[key];
						options[key] = value;
					};
				};

				if( m.config ){
					if( m.config.directory ){
						options.dispatchService = m.config.directory.dispatchService;
					};
				};

		        new AssignLayerOnDocumentCreation(options);

		        m.created = true;

			} else if( 'selectDocumentOnModuleIntroduction' === m.utilityType ){
				var options = {};

				if( typeof m.utilityOptions === 'object' ){
					for(var key in m.utilityOptions){
						var value = m.utilityOptions[key];
						options[key] = value;
					};
				};

				if( m.config ){
					if( m.config.directory ){
						options.dispatchService = m.config.directory.dispatchService;
					};
				};

		        new SelectDocumentOnModuleIntroduction(options);

		        m.created = true;

			} else if( 'selectDocumentOnFilterChange' === m.utilityType ){
				var options = {};

				if( typeof m.utilityOptions === 'object' ){
					for(var key in m.utilityOptions){
						var value = m.utilityOptions[key];
						options[key] = value;
					};
				};

				if( m.config ){
					if( m.config.directory ){
						options.dispatchService = m.config.directory.dispatchService;
					};
				};

		        new SelectDocumentOnFilterChange(options);

		        m.created = true;

			} else {
				if( $n2.mapUtilities
				 && typeof $n2.mapUtilities.HandleUtilityCreateRequests === 'function' ){
					$n2.mapUtilities.HandleUtilityCreateRequests(m, addr, dispatcher);
				};

				if( $n2.utilitiesModel
				 && typeof $n2.utilitiesModel.HandleUtilityCreateRequests === 'function' ){
					$n2.utilitiesModel.HandleUtilityCreateRequests(m, addr, dispatcher);
				};

				if( $n2.utilitiesChangeDetectors
					&& typeof $n2.utilitiesChangeDetectors.HandleUtilityCreateRequests === 'function' ){
					$n2.utilitiesChangeDetectors.HandleUtilityCreateRequests(m, addr, dispatcher);
				};
		    };
		};
	}
});

//--------------------------------------------------------------------------
$n2.utilities = {
	Service: Service
	,AssignLayerOnDocumentCreation: AssignLayerOnDocumentCreation
	,SelectDocumentOnModuleIntroduction: SelectDocumentOnModuleIntroduction
	,SelectDocumentOnFilterChange: SelectDocumentOnFilterChange
};

})(jQuery,nunaliit2);
<|endoftext|>


<commit_before>const showCustomPage = customNewTabUrl => {
	console.debug( '[showCustomPage] init', { customNewTabUrl } );

	// no tab URL set, do nothing
	if ( !customNewTabUrl || !customNewTabUrl.length ) {
		console.debug( '[showCustomPage] no tab url set' );
		return false;
	}

	document.querySelector( 'html' ).classList.add( 'cntp-has-loaded' );

	// The `type="content"` attribute is used for security purposes to avoid
	// giving the iframe a privileged context that could be used to
	// access browser (cookies, history, etc) or user files.
	// See https://mdn.io/Displaying_web_content_in_an_extension_without_security_issues
	const content = `<iframe type="content" class="cntp__iframe" src="${customNewTabUrl}"></iframe>`;

	document.body.innerHTML = content;

	return true;
};

self.port.on( 'showCustomPage', showCustomPage );
<commit_msg>fix: Avoid potential persistant XSS vulnerability<commit_after>const showCustomPage = customNewTabUrl => {
	console.debug( '[showCustomPage] init', { customNewTabUrl } );

	// no tab URL set, do nothing
	if ( !customNewTabUrl || !customNewTabUrl.length ) {
		console.debug( '[showCustomPage] no tab url set' );
		return false;
	}

	document.querySelector( 'html' ).classList.add( 'cntp-has-loaded' );

	// The `type="content"` attribute is used for security purposes to avoid
	// giving the iframe a privileged context that could be used to
	// access browser (cookies, history, etc) or user files.
	// See https://mdn.io/Displaying_web_content_in_an_extension_without_security_issues
	const iframe = document.createElement( 'iframe' );
	iframe.setAttribute( 'type', 'content' );
	iframe.className = 'cntp__iframe';
	iframe.src       = customNewTabUrl;

	document.body.textContent = '';
	document.body.appendChild( iframe );

	return true;
};

self.port.on( 'showCustomPage', showCustomPage );
<|endoftext|>


<commit_before>/**
 * Created by JongHyeok Choi on 2017. 5. 23..
 */

"use strict"

const hyd = require('hydrolysis');
const _ = require('underscore');
const xml2js = require('xml2js');
const fs = require('fs');

module.exports = (path) => {
    return analyze(path);
};

let analyze = (path)=> {
    //Analysis Polymer Element
    hyd.Analyzer.analyze(path)
        .then(settingData);
}

let parser = new xml2js.Parser();
let settingData = (analyzer) => {
let result = {
    template: {}
};

    analyzer.elements.forEach((element) => {
        fs.readFile('./format_example/Base.xml', function(err, data) {
            //parser.parseString(data, {'newline': '\n'}, (err, tmp) => {
                let $ = result.template["$"] = {};

                fnExcute(webstormHandler.is, $, element.is);
                fnExcute(webstormHandler.desc, $, "test");

                var builder = new xml2js.Builder();
                var xml = builder.buildObject(result);

                console.log(xml);

                fs.writeFile('./output/Result.xml', xml, (err) => {
                    if (err) throw err;
                    console.log('The file has been saved!');
                });
            //});
        });
    });
}

let fnExcute = (fn, ...args) => {
    return _.isFunction(fn) ? fn.apply(webstormHandler, args) : fn;
}

let webstormHandler = {
    is: (tmp, value) => {
        tmp.name = value;
    },
    desc: (tmp, value) => {
        tmp.description = value;
    }
}<commit_msg> - Mode 분리  - Editor별 Config 관리  -<commit_after>/**
 * Created by JongHyeok Choi on 2017. 5. 23..
 */

"use strict"

const hyd = require('hydrolysis');
const _ = require('underscore');
const xml2js = require('xml2js');
const fs = require('fs');

module.exports = (path) => {
    return analyze(path);
};

let analyze = (path) => {
    //Analysis Polymer Element
    hyd.Analyzer.analyze(path)
        .then(settingData);
}

let parser = new xml2js.Parser();
let settingData = (analyzer) => {
    let result = {
        template: [] // Template 태그는 여러 개의 태그를 담는다
    };

    //기본 템플릿 불러오기
    fs.readFile('./format_example/Base.xml', function (err, data) {
        parser.parseString(data, (err, tmp) => {

            //Element별로 처리
            analyzer.elements.forEach((element) => {
                let eleObj = {};

                fnExcute(webstormHandler.is, eleObj, element.is);
                fnExcute(webstormHandler.desc, eleObj, "test");

                element.properties.forEach((p) => {
                    //Properties Type이 getter 또는 Function이 아닐 때
                    if (p.type === "" || p.type === 'Function') {

                    } else if (snippetConfig.mode === MODE.ALL) {
                        console.log(p.name, p.type);

                    } else if (snippetConfig.mode === MODE.EXIST_ANNOTATION) {

                    } else if (snippetConfig.mode === MODE.EXIST_DESC) {

                    } else if (snippetConfig.mode === MODE.CUSTOM_ANNOTATION) {

                    }
                });

                //Push Data
                result.template.push({template: eleObj});

                //JSON to XML
                var builder = new xml2js.Builder();
                var xml = builder.buildObject(result);

                //Additory Working for Output File
                //Get TemplateSet

                //Write File
                fs.writeFile('./output/Result.xml', xml, (err) => {
                    if (err) throw err;
                    console.log('The file has been saved!');
                });
            });
        });
    });
}

let snippetConfig = {
    get mode() {
        return MODE.ALL;
    },
};

let MODE = {
    //공통적으로 Function, Getter 제외

    ALL: 1, //모든 Property에 대해
    EXIST_ANNOTATION: 2, //Annotation이 있는 태그에 대해
    EXIST_DESC: 3,  //Comment가 존재하는 경우
    CUSTOM_ANNOTATION: 4 //특정 어노테이션이 있는 경우
};

//fn이 함수이면 결과 값 반환 아니면 undefined
let fnExcute = (fn, ...args) => {
    if (_.isFunction(fn)) {
        return fn.apply(webstormHandler, args);
    }
    return undefined;
}

//Webstrom Code Snippet Config Handler
let webstormHandler = {
    is: (tmp, value) => {
        tmp.name = value;
    },
    desc: (tmp, value) => {
        tmp.description = value;
    }
}

//Atom Code Snippet Config Handler
let atomHandler = {
    is: (tmp, value) => {
        tmp.name = value;
    },
    desc: (tmp, value) => {
        tmp.description = value;
    }
}

//Sublime Code Snippet Config Handler
let sublimeHandler = {
    is: (tmp, value) => {
        tmp.name = value;
    },
    desc: (tmp, value) => {
        tmp.description = value;
    }
}

//VS Code Snippet Config Handler
let vscodeHandler = {
    is: (tmp, value) => {
        tmp.name = value;
    },
    desc: (tmp, value) => {
        tmp.description = value;
    }
}<|endoftext|>


<commit_before>/* jshint strict: false, sub: true */
/* global print */
'use strict';

// //////////////////////////////////////////////////////////////////////////////
// / DISCLAIMER
// /
// / Copyright 2016 ArangoDB GmbH, Cologne, Germany
// / Copyright 2014 triagens GmbH, Cologne, Germany
// /
// / Licensed under the Apache License, Version 2.0 (the "License")
// / you may not use this file except in compliance with the License.
// / You may obtain a copy of the License at
// /
// /     http://www.apache.org/licenses/LICENSE-2.0
// /
// / Unless required by applicable law or agreed to in writing, software
// / distributed under the License is distributed on an "AS IS" BASIS,
// / WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// / See the License for the specific language governing permissions and
// / limitations under the License.
// /
// / Copyright holder is ArangoDB GmbH, Cologne, Germany
// /
// / @author Max Neunhoeffer
// //////////////////////////////////////////////////////////////////////////////

const functionsDocumentation = {
  'recovery': 'run recovery tests'
};
const optionsDocumentation = [
];

const fs = require('fs');
const pu = require('@arangodb/process-utils');
const tu = require('@arangodb/test-utils');
const _ = require('lodash');

const toArgv = require('internal').toArgv;

const RED = require('internal').COLORS.COLOR_RED;
const RESET = require('internal').COLORS.COLOR_RESET;
const BLUE = require('internal').COLORS.COLOR_BLUE;

const testPaths = {
  'recovery': [tu.pathForTesting('server/recovery')]
};

// //////////////////////////////////////////////////////////////////////////////
// / @brief TEST: recovery
// //////////////////////////////////////////////////////////////////////////////

function runArangodRecovery (params) {
  let argv = [];

  let binary = pu.ARANGOD_BIN;

  if (params.setup) {
    params.options.disableMonitor = true;
    params.testDir = fs.join(params.tempDir, `${params.count}`);
    pu.cleanupDBDirectoriesAppend(params.testDir);
    let dataDir = fs.join(params.testDir, 'data');
    let appDir = fs.join(params.testDir, 'app');
    let tmpDir = fs.join(params.testDir, 'tmp');
    fs.makeDirectoryRecursive(params.testDir);
    fs.makeDirectoryRecursive(dataDir);
    fs.makeDirectoryRecursive(tmpDir);
    fs.makeDirectoryRecursive(appDir);

    let args = pu.makeArgs.arangod(params.options, appDir, '', tmpDir);
    // enable development debugging if extremeVerbosity is set
    if (params.options.extremeVerbosity === true) {
      args['log.level'] = 'development=info';
    }
    args = Object.assign(args, params.options.extraArgs);
    args = Object.assign(args, {
      'wal.reserve-logfiles': 1,
      'rocksdb.wal-file-timeout-initial': 10,
      'database.directory': fs.join(dataDir + 'db'),
      'server.rest-server': 'false',
      'replication.auto-start': 'true',
      'javascript.script': params.script
    });
    params.args = args;

    argv = toArgv(
      Object.assign(params.args,
                    {
                      'javascript.script-parameter': 'setup'
                    }
                   )
    );
  } else {
    argv = toArgv(
      Object.assign(params.args,
                    {
                      'log.foreground-tty': 'true',
                      'wal.ignore-logfile-errors': 'true',
                      'database.ignore-datafile-errors': 'false', // intentionally false!
                      'javascript.script-parameter': 'recovery'
                    }
                   )
    );
    if (params.options.rr) {
      binary = 'rr';
      argv.unshift(pu.ARANGOD_BIN);
    }
  }
  params.instanceInfo.pid = pu.executeAndWait(
    binary,
    argv,
    params.options,
    'recovery',
    params.instanceInfo.rootDir,
    params.setup,
    !params.setup && params.options.coreCheck);
}

function recovery (options) {
  if (!global.ARANGODB_CLIENT_VERSION(true)['failure-tests'] ||
      global.ARANGODB_CLIENT_VERSION(true)['failure-tests'] === 'false') {
    return {
      recovery: {
        status: false,
        message: 'failure-tests not enabled. please recompile with -DUSE_FAILURE_TESTS=On'
      },
      status: false
    };
  }

  let results = {
    status: true
  };

  let recoveryTests = tu.scanTestPaths(testPaths.recovery);

  recoveryTests = tu.splitBuckets(options, recoveryTests);

  let count = 0;
  let orgTmp = process.env.TMPDIR;
  let tempDir = fs.join(fs.getTempPath(), 'crashtmp');
  fs.makeDirectoryRecursive(tempDir);
  process.env.TMPDIR = tempDir;
  pu.cleanupDBDirectoriesAppend(tempDir);

  for (let i = 0; i < recoveryTests.length; ++i) {
    let test = recoveryTests[i];
    let filtered = {};

    if (tu.filterTestcaseByOptions(test, options, filtered)) {
      count += 1;
      ////////////////////////////////////////////////////////////////////////
      print(BLUE + "running setup of test " + count + " - " + test + RESET);
      let params = {
        tempDir: tempDir,
        instanceInfo: {
          rootDir: pu.UNITTESTS_DIR
        },
        options: _.cloneDeep(options),
        script: test,
        setup: true,
        count: count,
        testDir: ""
      };
      runArangodRecovery(params);

      ////////////////////////////////////////////////////////////////////////
      print(BLUE + "running recovery of test " + count + " - " + test + RESET);
      params.options.disableMonitor = options.disableMonitor;
      params.setup = false;
      tu.writeTestResult(params.args['temp.path'], {
        failed: 1,
        status: false,
        message: "unable to run recovery test " + test,
        duration: -1
      });
      runArangodRecovery(params);

      results[test] = tu.readTestResult(
        params.args['temp.path'],
        {
          status: false
        }
      );
      if (!results[test].status) {
        print("Not cleaning up " + params.testDir);
        results.status = false;
      }
      else {
        pu.cleanupLastDirectory(params.options);
      }
    } else {
      if (options.extremeVerbosity) {
        print('Skipped ' + test + ' because of ' + filtered.filter);
      }
    }
  }
  process.env.TMPDIR = orgTmp;
  if (count === 0) {
    print(RED + 'No testcase matched the filter.' + RESET);
    return {
      ALLTESTS: {
        status: false,
        skipped: true
      },
      status: false
    };
  }

  return results;
}

exports.setup = function (testFns, defaultFns, opts, fnDocs, optionsDoc, allTestPaths) {
  Object.assign(allTestPaths, testPaths);
  testFns['recovery'] = recovery;
  for (var attrname in functionsDocumentation) { fnDocs[attrname] = functionsDocumentation[attrname]; }
  for (var i = 0; i < optionsDocumentation.length; i++) { optionsDoc.push(optionsDocumentation[i]); }
};
<commit_msg>try..catch to avoid useless failures<commit_after>/* jshint strict: false, sub: true */
/* global print */
'use strict';

// //////////////////////////////////////////////////////////////////////////////
// / DISCLAIMER
// /
// / Copyright 2016 ArangoDB GmbH, Cologne, Germany
// / Copyright 2014 triagens GmbH, Cologne, Germany
// /
// / Licensed under the Apache License, Version 2.0 (the "License")
// / you may not use this file except in compliance with the License.
// / You may obtain a copy of the License at
// /
// /     http://www.apache.org/licenses/LICENSE-2.0
// /
// / Unless required by applicable law or agreed to in writing, software
// / distributed under the License is distributed on an "AS IS" BASIS,
// / WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// / See the License for the specific language governing permissions and
// / limitations under the License.
// /
// / Copyright holder is ArangoDB GmbH, Cologne, Germany
// /
// / @author Max Neunhoeffer
// //////////////////////////////////////////////////////////////////////////////

const functionsDocumentation = {
  'recovery': 'run recovery tests'
};
const optionsDocumentation = [
];

const fs = require('fs');
const pu = require('@arangodb/process-utils');
const tu = require('@arangodb/test-utils');
const _ = require('lodash');

const toArgv = require('internal').toArgv;

const RED = require('internal').COLORS.COLOR_RED;
const RESET = require('internal').COLORS.COLOR_RESET;
const BLUE = require('internal').COLORS.COLOR_BLUE;

const testPaths = {
  'recovery': [tu.pathForTesting('server/recovery')]
};

// //////////////////////////////////////////////////////////////////////////////
// / @brief TEST: recovery
// //////////////////////////////////////////////////////////////////////////////

function runArangodRecovery (params) {
  let argv = [];

  let binary = pu.ARANGOD_BIN;

  if (params.setup) {
    params.options.disableMonitor = true;
    params.testDir = fs.join(params.tempDir, `${params.count}`);
    pu.cleanupDBDirectoriesAppend(params.testDir);
    let dataDir = fs.join(params.testDir, 'data');
    let appDir = fs.join(params.testDir, 'app');
    let tmpDir = fs.join(params.testDir, 'tmp');
    fs.makeDirectoryRecursive(params.testDir);
    fs.makeDirectoryRecursive(dataDir);
    fs.makeDirectoryRecursive(tmpDir);
    fs.makeDirectoryRecursive(appDir);

    let args = pu.makeArgs.arangod(params.options, appDir, '', tmpDir);
    // enable development debugging if extremeVerbosity is set
    if (params.options.extremeVerbosity === true) {
      args['log.level'] = 'development=info';
    }
    args = Object.assign(args, params.options.extraArgs);
    args = Object.assign(args, {
      'wal.reserve-logfiles': 1,
      'rocksdb.wal-file-timeout-initial': 10,
      'database.directory': fs.join(dataDir + 'db'),
      'server.rest-server': 'false',
      'replication.auto-start': 'true',
      'javascript.script': params.script
    });
    params.args = args;

    argv = toArgv(
      Object.assign(params.args,
                    {
                      'javascript.script-parameter': 'setup'
                    }
                   )
    );
  } else {
    argv = toArgv(
      Object.assign(params.args,
                    {
                      'log.foreground-tty': 'true',
                      'wal.ignore-logfile-errors': 'true',
                      'database.ignore-datafile-errors': 'false', // intentionally false!
                      'javascript.script-parameter': 'recovery'
                    }
                   )
    );
    if (params.options.rr) {
      binary = 'rr';
      argv.unshift(pu.ARANGOD_BIN);
    }
  }
  params.instanceInfo.pid = pu.executeAndWait(
    binary,
    argv,
    params.options,
    'recovery',
    params.instanceInfo.rootDir,
    params.setup,
    !params.setup && params.options.coreCheck);
}

function recovery (options) {
  if (!global.ARANGODB_CLIENT_VERSION(true)['failure-tests'] ||
      global.ARANGODB_CLIENT_VERSION(true)['failure-tests'] === 'false') {
    return {
      recovery: {
        status: false,
        message: 'failure-tests not enabled. please recompile with -DUSE_FAILURE_TESTS=On'
      },
      status: false
    };
  }

  let results = {
    status: true
  };

  let recoveryTests = tu.scanTestPaths(testPaths.recovery);

  recoveryTests = tu.splitBuckets(options, recoveryTests);

  let count = 0;
  let orgTmp = process.env.TMPDIR;
  let tempDir = fs.join(fs.getTempPath(), 'crashtmp');
  fs.makeDirectoryRecursive(tempDir);
  process.env.TMPDIR = tempDir;
  pu.cleanupDBDirectoriesAppend(tempDir);

  for (let i = 0; i < recoveryTests.length; ++i) {
    let test = recoveryTests[i];
    let filtered = {};

    if (tu.filterTestcaseByOptions(test, options, filtered)) {
      count += 1;
      ////////////////////////////////////////////////////////////////////////
      print(BLUE + "running setup of test " + count + " - " + test + RESET);
      let params = {
        tempDir: tempDir,
        instanceInfo: {
          rootDir: pu.UNITTESTS_DIR
        },
        options: _.cloneDeep(options),
        script: test,
        setup: true,
        count: count,
        testDir: ""
      };
      runArangodRecovery(params);

      ////////////////////////////////////////////////////////////////////////
      print(BLUE + "running recovery of test " + count + " - " + test + RESET);
      params.options.disableMonitor = options.disableMonitor;
      params.setup = false;
      try {
        tu.writeTestResult(params.args['temp.path'], {
          failed: 1,
          status: false,
          message: "unable to run recovery test " + test,
          duration: -1
        });
      } catch (er) {}
      runArangodRecovery(params);

      results[test] = tu.readTestResult(
        params.args['temp.path'],
        {
          status: false
        }
      );
      if (!results[test].status) {
        print("Not cleaning up " + params.testDir);
        results.status = false;
      }
      else {
        pu.cleanupLastDirectory(params.options);
      }
    } else {
      if (options.extremeVerbosity) {
        print('Skipped ' + test + ' because of ' + filtered.filter);
      }
    }
  }
  process.env.TMPDIR = orgTmp;
  if (count === 0) {
    print(RED + 'No testcase matched the filter.' + RESET);
    return {
      ALLTESTS: {
        status: false,
        skipped: true
      },
      status: false
    };
  }

  return results;
}

exports.setup = function (testFns, defaultFns, opts, fnDocs, optionsDoc, allTestPaths) {
  Object.assign(allTestPaths, testPaths);
  testFns['recovery'] = recovery;
  for (var attrname in functionsDocumentation) { fnDocs[attrname] = functionsDocumentation[attrname]; }
  for (var i = 0; i < optionsDocumentation.length; i++) { optionsDoc.push(optionsDocumentation[i]); }
};
<|endoftext|>


<commit_before>var fs = require("fs");
var sqlite3 = require("sqlite3").verbose();
var settings = require('./settings.js');

var Database = function() {
	var scope = this;
	var insertStatement;
	var selectStatement;
	var db = null;

	this.init = function() {
		if(!global.db) {
			if(!fs.existsSync(settings.DATABASE_FILE)) {
				var err = fs.writeFileSync(settings.DATABASE_FILE, '', { flags: 'wx' });
				if(err) { console.log(err); }
			}
			global.db = new sqlite3.Database(settings.DATABASE_FILE);
		}
		db = global.db;
		this.createTable();
		insertStatement = db.prepare("INSERT INTO temperature (date, temperature) VALUES($date, $temperature)");
		selectStatement = db.prepare("SELECT date, temperature FROM temperature WHERE date >= $dateStart AND date <= $dateEnd");
	};

	this.createTable = function() {
		db.serialize(function() {
			db.run("CREATE TABLE IF NOT EXISTS temperature (date NUM, temperature NUM)");
		});
	};

	this.insert = function(data, callback) {
		insertStatement.run({$date:data.date, $temperature:data.temperature}, function(err) {
    	if(err) { console.log(err); }
			callback(err);
		});
	};

	this.get = function(dateStart, dateEnd, callback) {
		selectStatement.all({$dateStart:dateStart, $dateEnd:dateEnd}, function(err, results) {
			if(err) { console.log(err); }
			callback(results);
  	});
	};

	this.extremes = function(dateStart, dateEnd, callback) {
		var extremes = {
			min: {},
			max: {}
		};

		var filterQuery = dateStart || dateEnd ? " WHERE" : "";
		if(dateStart) {
			filterQuery += " date >= " + dateStart.toString();
		}
		if(dateEnd) {
			if(dateStart) {
				filterQuery += " AND";
			}
			filterQuery += " date < " + dateEnd.toString();
		}

		db.get('SELECT date, MIN(temperature) as temperature FROM temperature' + filterQuery, function(err, row) {
			if(err) { console.log(err); }
			extremes.min = row;
			db.get('SELECT date, MAX(temperature) as temperature FROM temperature' + filterQuery, function(err, row) {
				if(err) { console.log(err); }
				extremes.max = row;
				callback(extremes);
			});
		});
	};

	this.getLastEntry = function(callback) {
		db.get('SELECT date, temperature FROM temperature ORDER BY date DESC LIMIT 1', function(err, row) {
			if(err) { console.log(err); }
			callback(row);
		});
	};

};

module.exports = new Database();
<commit_msg>Database.js ES6<commit_after>(function() {
  'use strict';
  let fs = require('fs');
  let sqlite3 = require('sqlite3').verbose();
  let settings = require('./settings.js');

  class Database {

    constructor() {
      this.insertStatement = null;
      this.selectSTatement = null;
      this.db = null;
    }

    init() {
      if (!global.db) {
        if (!fs.existsSync(settings.DATABASE_FILE)) {
          let err = fs.writeFileSync(settings.DATABASE_FILE, '', {
            flags: 'wx',
          });
          if (err) {
            console.log(err);
          }
        }
        global.db = new sqlite3.Database(settings.DATABASE_FILE);
      }
      this.db = global.db;
      this.createTable();
      this.insertStatement = this.db.prepare('INSERT INTO temperature (date, temperature) VALUES($date, $temperature)');
      this.selectStatement = this.db.prepare('SELECT date, temperature FROM temperature WHERE date >= $dateStart AND date <= $dateEnd');
    }

    createTable() {
      this.db.serialize(() => {
        this.db.run('CREATE TABLE IF NOT EXISTS temperature (date NUM, temperature NUM)');
      });
    }

    insert(data, callback) {
      this.insertStatement.run({
        $date: data.date,
        $temperature: data.temperature,
      }, function(err) {
        if (err) {
          console.log(err);
        }
        callback(err);
      });
    }

    get(dateStart, dateEnd, callback) {
      this.selectStatement.all({
        $dateStart: dateStart,
        $dateEnd: dateEnd,
      }, function(err, results) {
        if (err) {
          console.log(err);
        }
        callback(results);
      });
    }

    extremes(dateStart, dateEnd, callback) {
      let extremes = {
        min: {},
        max: {},
      };

      let filterQuery = dateStart || dateEnd ? ' WHERE' : '';
      if (dateStart) {
        filterQuery += ' date >= ' + dateStart.toString();
      }
      if (dateEnd) {
        if (dateStart) {
          filterQuery += ' AND';
        }
        filterQuery += ' date < ' + dateEnd.toString();
      }

      this.db.get('SELECT date, MIN(temperature) as temperature FROM temperature' + filterQuery, (err, row) => {
        if (err) {
          console.log(err);
        }
        extremes.min = row;
        this.db.get('SELECT date, MAX(temperature) as temperature FROM temperature' + filterQuery, (err, row) => {
          if (err) {
            console.log(err);
          }
          extremes.max = row;
          callback(extremes);
        });
      });
    }

    getLastEntry(callback) {
      this.db.get('SELECT date, temperature FROM temperature ORDER BY date DESC LIMIT 1', function(err, row) {
        if (err) {
          console.log(err);
        }
        callback(row);
      });
    }
  }

  module.exports = new Database();
}());
<|endoftext|>


<commit_before>/**
 * Copyright 2018-present Facebook.
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 * @format
 */

import type {DeviceType, DeviceShell} from './BaseDevice.js';

import {Priority} from 'adbkit-logcat-fb';
import child_process from 'child_process';
import BaseDevice from './BaseDevice.js';

type ADBClient = any;

export default class AndroidDevice extends BaseDevice {
  constructor(
    serial: string,
    deviceType: DeviceType,
    title: string,
    adb: ADBClient,
  ) {
    super(serial, deviceType, title);
    this.adb = adb;
    if (deviceType == 'physical') {
      this.supportedPlugins.push('DeviceCPU');
    }

    this.adb.openLogcat(this.serial).then(reader => {
      reader.on('entry', entry => {
        if (this.logListeners.size > 0) {
          let type = 'unknown';
          if (entry.priority === Priority.VERBOSE) {
            type = 'verbose';
          }
          if (entry.priority === Priority.DEBUG) {
            type = 'debug';
          }
          if (entry.priority === Priority.INFO) {
            type = 'info';
          }
          if (entry.priority === Priority.WARN) {
            type = 'warn';
          }
          if (entry.priority === Priority.ERROR) {
            type = 'error';
          }
          if (entry.priority === Priority.FATAL) {
            type = 'fatal';
          }

          this.notifyLogListeners({
            tag: entry.tag,
            pid: entry.pid,
            tid: entry.tid,
            message: entry.message,
            date: entry.date,
            type,
          });
        }
      });
    });
  }

  supportedPlugins = [
    'DeviceLogs',
    'DeviceShell',
    'DeviceFiles',
    'DeviceScreen',
  ];
  icon = 'icons/android.svg';
  os = 'Android';
  adb: ADBClient;
  pidAppMapping: {[key: number]: string} = {};
  logReader: any;

  supportedColumns(): Array<string> {
    return ['date', 'pid', 'tid', 'tag', 'message', 'type', 'time'];
  }

  reverse(): Promise<void> {
    if (this.deviceType === 'physical') {
      return this.adb
        .reverse(this.serial, 'tcp:8088', 'tcp:8088')
        .then(_ => this.adb.reverse(this.serial, 'tcp:8089', 'tcp:8089'));
    } else {
      return Promise.resolve();
    }
  }

  spawnShell(): DeviceShell {
    return child_process.spawn('adb', ['-s', this.serial, 'shell', '-t', '-t']);
  }
}
<commit_msg>Run adb reverse for emulators too<commit_after>/**
 * Copyright 2018-present Facebook.
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 * @format
 */

import type {DeviceType, DeviceShell} from './BaseDevice.js';

import {Priority} from 'adbkit-logcat-fb';
import child_process from 'child_process';
import BaseDevice from './BaseDevice.js';
import {SECURE_PORT, INSECURE_PORT} from '../server';

type ADBClient = any;

export default class AndroidDevice extends BaseDevice {
  constructor(
    serial: string,
    deviceType: DeviceType,
    title: string,
    adb: ADBClient,
  ) {
    super(serial, deviceType, title);
    this.adb = adb;
    if (deviceType == 'physical') {
      this.supportedPlugins.push('DeviceCPU');
    }

    this.adb.openLogcat(this.serial).then(reader => {
      reader.on('entry', entry => {
        if (this.logListeners.size > 0) {
          let type = 'unknown';
          if (entry.priority === Priority.VERBOSE) {
            type = 'verbose';
          }
          if (entry.priority === Priority.DEBUG) {
            type = 'debug';
          }
          if (entry.priority === Priority.INFO) {
            type = 'info';
          }
          if (entry.priority === Priority.WARN) {
            type = 'warn';
          }
          if (entry.priority === Priority.ERROR) {
            type = 'error';
          }
          if (entry.priority === Priority.FATAL) {
            type = 'fatal';
          }

          this.notifyLogListeners({
            tag: entry.tag,
            pid: entry.pid,
            tid: entry.tid,
            message: entry.message,
            date: entry.date,
            type,
          });
        }
      });
    });
  }

  supportedPlugins = [
    'DeviceLogs',
    'DeviceShell',
    'DeviceFiles',
    'DeviceScreen',
  ];
  icon = 'icons/android.svg';
  os = 'Android';
  adb: ADBClient;
  pidAppMapping: {[key: number]: string} = {};
  logReader: any;

  supportedColumns(): Array<string> {
    return ['date', 'pid', 'tid', 'tag', 'message', 'type', 'time'];
  }

  reverse(): Promise<void> {
    return this.adb
      .reverse(this.serial, `tcp:${SECURE_PORT}`, `tcp:${SECURE_PORT}`)
      .then(() =>
        this.adb.reverse(
          this.serial,
          `tcp:${INSECURE_PORT}`,
          `tcp:${INSECURE_PORT}`,
        ),
      );
  }

  spawnShell(): DeviceShell {
    return child_process.spawn('adb', ['-s', this.serial, 'shell', '-t', '-t']);
  }
}
<|endoftext|>