<commit_before>/*
 * Minio Javascript Library for Amazon S3 Compatible Cloud Storage, (C) 2015 Minio, Inc.
 *
 * 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.
 */

import stream from 'stream'
import _ from 'lodash'

// All characters in string which are NOT unreserved should be percent encoded.
// Unreserved characers are : ALPHA / DIGIT / "-" / "." / "_" / "~"
// Reference https://tools.ietf.org/html/rfc3986#section-2.2
export function uriEscape(string) {
  return string.split('').reduce((acc, elem) => {
    let buf = new Buffer(elem)
    if (buf.length === 1) {
      // length 1 indicates that elem is not a unicode character.
      // Check if it is an unreserved characer.
      if ('A' <= elem && elem <= 'Z' ||
	  'a' <= elem && elem <= 'z' ||
	  '0' <= elem && elem <= '9' ||
	  elem === '_' ||
	  elem === '.' ||
	  elem === '~' ||
	  elem === '-')
      {
	// Unreserved characer should not be encoded.
	acc = acc + elem
	return acc
      }
    }
    // elem needs encoding - i.e elem should be encoded if it's not unreserved
    // character or if it's a unicode character.
    for (var i = 0; i < buf.length; i++) {
      acc = acc + "%" + buf[i].toString(16).toUpperCase()
    }
    return acc
  }, '')
}

export function uriResourceEscape(string) {
  return uriEscape(string).replace(/%2F/g, '/')
}

export function getScope(region, date) {
  return `${date.format('YYYYMMDD')}/${region}/s3/aws4_request`
}

// isAmazonEndpoint - true if endpoint is 's3.amazonaws.com'.
export function isAmazonEndpoint(endpoint) {
  return endpoint === 's3.amazonaws.com'
}

// isVirtualHostStyle - verify if bucket name is support with virtual
// hosts. bucketNames with periods should be always treated as path
// style if the protocol is 'https:', this is due to SSL wildcard
// limitation. For all other buckets and Amazon S3 endpoint we will
// default to virtual host style.
export function isVirtualHostStyle(endpoint, protocol, bucket) {
  if (protocol === 'https:' && bucket.indexOf('.') > -1) {
    return false
  }
  return isAmazonEndpoint(endpoint)
}

// isValidEndpoint - true if endpoint is valid domain.
export function isValidEndpoint(endpoint) {
  if (!isValidDomain(endpoint)) {
    return false
  }
  // Endpoint matches amazon, make sure its 's3.amazonaws.com'
  if (endpoint.match('.amazonaws.com$')) {
    if (!isAmazonEndpoint(endpoint)) {
      return false
    }
  }
  // Returning true for all other cases.
  return true
}

// isValidDomain - true if input host is a valid domain.
export function isValidDomain(host) {
  if (!isString(host)) return false
  // See RFC 1035, RFC 3696.
  if (host.length === 0 || host.length > 255) {
    return false
  }
  // Host cannot start or end with a '-'
  if (host[0] === '-' || host.substr(-1) === '-') {
    return false
  }
  // Host cannot start or end with a '_'
  if (host[0] === '_' || host.substr(-1) === '_') {
    return false
  }
  // Host cannot start or end with a '.'
  if (host[0] === '.' || host.substr(-1) === '.') {
    return false
  }
  var alphaNumerics = '`~!@#$%^&*()+={}[]|\\\"\';:><?/'.split('')
  // All non alphanumeric characters are invalid.
  for (var i in alphaNumerics) {
    if (host.indexOf(alphaNumerics[i]) > -1) {
      return false
    }
  }
  // No need to regexp match, since the list is non-exhaustive.
  // We let it be valid and fail later.
  return true
}

// isValidPort - is input port valid.
export function isValidPort(port) {
  // verify if port is a number.
  if (!isNumber(port)) return false
  // port cannot be negative.
  if (port < 0) return false
  // port '0' is valid and special case return true.
  if (port === 0) return true
  var min_port = 1;
  var max_port = 65535;
  // Verify if port is in range.
  return port >= min_port && port <= max_port
}

export function isValidBucketName(bucket) {
  if (!isString(bucket)) return false

  // bucket length should be less than and no more than 63
  // characters long.
  if (bucket.length < 3 || bucket.length > 63) {
    return false
  }
  // bucket with successive periods is invalid.
  if (bucket.indexOf('..') > -1) {
    return false
  }
  // bucket cannot have ip address style.
  if (bucket.match(/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/)) {
    return false
  }
  // bucket should begin with alphabet/number and end with alphabet/number,
  // with alphabet/number/.- in the middle.
  if (bucket.match(/^[a-z0-9][a-z0-9.-]+[a-z0-9]$/)) {
    return true
  }
  return false
}

// check if objectName is a valid object name
export function isValidObjectName(objectName) {
  if (!isValidPrefix(objectName)) return false
  if (objectName.length === 0) return false
  return true
}

// check if prefix is valid
export function isValidPrefix(prefix) {
  if (!isString(prefix)) return false
  if (prefix.length > 1024) return false
  return true
}

// check if typeof arg number
export function isNumber(arg) {
  return typeof(arg) === 'number'
}

// check if typeof arg function
export function isFunction(arg) {
  return typeof(arg) === 'function';
}

// check if typeof arg string
export function isString(arg) {
  return typeof(arg) === 'string';
}

// check if typeof arg object
export function isObject(arg) {
  return typeof(arg) === 'object' && arg !== null;
}

// check if object is readable stream
export function isReadableStream(arg) {
  return isObject(arg) && isFunction(arg._read)
}

// check if arg is boolean
export function isBoolean(arg) {
  return typeof(arg) === 'boolean'
}

// check if arg is array
export function isArray(arg) {
  return Array.isArray(arg)
}

// check if arg is Date
export function isDate(arg) {
  return arg._isAMomentObject
}

// pipesetup sets up pipe() from left to right os streams array
// pipesetup will also make sure that error emitted at any of the upstream Stream
// will be emited at the last stream. This makes error handling simple
export function pipesetup(...streams) {
  return streams.reduce((src, dst) => {
    src.on('error', err => dst.emit('error', err))
    return src.pipe(dst)
  })
}

// return a Readable stream that emits data
export function readableStream(data) {
  var s = new stream.Readable()
  s._read = () => {}
  s.push(data)
  s.push(null)
  return s
}
<commit_msg>Code: Spelling corrections in helpers.js (#496)<commit_after>/*
 * Minio Javascript Library for Amazon S3 Compatible Cloud Storage, (C) 2015 Minio, Inc.
 *
 * 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.
 */

import stream from 'stream'
import _ from 'lodash'

// All characters in string which are NOT unreserved should be percent encoded.
// Unreserved characers are : ALPHA / DIGIT / "-" / "." / "_" / "~"
// Reference https://tools.ietf.org/html/rfc3986#section-2.2
export function uriEscape(string) {
  return string.split('').reduce((acc, elem) => {
    let buf = new Buffer(elem)
    if (buf.length === 1) {
      // length 1 indicates that elem is not a unicode character.
      // Check if it is an unreserved characer.
      if ('A' <= elem && elem <= 'Z' ||
	  'a' <= elem && elem <= 'z' ||
	  '0' <= elem && elem <= '9' ||
	  elem === '_' ||
	  elem === '.' ||
	  elem === '~' ||
	  elem === '-')
      {
	// Unreserved characer should not be encoded.
	acc = acc + elem
	return acc
      }
    }
    // elem needs encoding - i.e elem should be encoded if it's not unreserved
    // character or if it's a unicode character.
    for (var i = 0; i < buf.length; i++) {
      acc = acc + "%" + buf[i].toString(16).toUpperCase()
    }
    return acc
  }, '')
}

export function uriResourceEscape(string) {
  return uriEscape(string).replace(/%2F/g, '/')
}

export function getScope(region, date) {
  return `${date.format('YYYYMMDD')}/${region}/s3/aws4_request`
}

// isAmazonEndpoint - true if endpoint is 's3.amazonaws.com'.
export function isAmazonEndpoint(endpoint) {
  return endpoint === 's3.amazonaws.com'
}

// isVirtualHostStyle - verify if bucket name is support with virtual
// hosts. bucketNames with periods should be always treated as path
// style if the protocol is 'https:', this is due to SSL wildcard
// limitation. For all other buckets and Amazon S3 endpoint we will
// default to virtual host style.
export function isVirtualHostStyle(endpoint, protocol, bucket) {
  if (protocol === 'https:' && bucket.indexOf('.') > -1) {
    return false
  }
  return isAmazonEndpoint(endpoint)
}

// isValidEndpoint - true if endpoint is valid domain.
export function isValidEndpoint(endpoint) {
  if (!isValidDomain(endpoint)) {
    return false
  }
  // Endpoint matches amazon, make sure its 's3.amazonaws.com'
  if (endpoint.match('.amazonaws.com$')) {
    if (!isAmazonEndpoint(endpoint)) {
      return false
    }
  }
  // Returning true for all other cases.
  return true
}

// isValidDomain - true if input host is a valid domain.
export function isValidDomain(host) {
  if (!isString(host)) return false
  // See RFC 1035, RFC 3696.
  if (host.length === 0 || host.length > 255) {
    return false
  }
  // Host cannot start or end with a '-'
  if (host[0] === '-' || host.substr(-1) === '-') {
    return false
  }
  // Host cannot start or end with a '_'
  if (host[0] === '_' || host.substr(-1) === '_') {
    return false
  }
  // Host cannot start or end with a '.'
  if (host[0] === '.' || host.substr(-1) === '.') {
    return false
  }
  var alphaNumerics = '`~!@#$%^&*()+={}[]|\\\"\';:><?/'.split('')
  // All non alphanumeric characters are invalid.
  for (var i in alphaNumerics) {
    if (host.indexOf(alphaNumerics[i]) > -1) {
      return false
    }
  }
  // No need to regexp match, since the list is non-exhaustive.
  // We let it be valid and fail later.
  return true
}

// isValidPort - is input port valid.
export function isValidPort(port) {
  // verify if port is a number.
  if (!isNumber(port)) return false
  // port cannot be negative.
  if (port < 0) return false
  // port '0' is valid and special case return true.
  if (port === 0) return true
  var min_port = 1;
  var max_port = 65535;
  // Verify if port is in range.
  return port >= min_port && port <= max_port
}

export function isValidBucketName(bucket) {
  if (!isString(bucket)) return false

  // bucket length should be less than and no more than 63
  // characters long.
  if (bucket.length < 3 || bucket.length > 63) {
    return false
  }
  // bucket with successive periods is invalid.
  if (bucket.indexOf('..') > -1) {
    return false
  }
  // bucket cannot have ip address style.
  if (bucket.match(/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/)) {
    return false
  }
  // bucket should begin with alphabet/number and end with alphabet/number,
  // with alphabet/number/.- in the middle.
  if (bucket.match(/^[a-z0-9][a-z0-9.-]+[a-z0-9]$/)) {
    return true
  }
  return false
}

// check if objectName is a valid object name
export function isValidObjectName(objectName) {
  if (!isValidPrefix(objectName)) return false
  if (objectName.length === 0) return false
  return true
}

// check if prefix is valid
export function isValidPrefix(prefix) {
  if (!isString(prefix)) return false
  if (prefix.length > 1024) return false
  return true
}

// check if typeof arg number
export function isNumber(arg) {
  return typeof(arg) === 'number'
}

// check if typeof arg function
export function isFunction(arg) {
  return typeof(arg) === 'function';
}

// check if typeof arg string
export function isString(arg) {
  return typeof(arg) === 'string';
}

// check if typeof arg object
export function isObject(arg) {
  return typeof(arg) === 'object' && arg !== null;
}

// check if object is readable stream
export function isReadableStream(arg) {
  return isObject(arg) && isFunction(arg._read)
}

// check if arg is boolean
export function isBoolean(arg) {
  return typeof(arg) === 'boolean'
}

// check if arg is array
export function isArray(arg) {
  return Array.isArray(arg)
}

// check if arg is Date
export function isDate(arg) {
  return arg._isAMomentObject
}

// pipesetup sets up pipe() from left to right os streams array
// pipesetup will also make sure that error emitted at any of the upstream Stream
// will be emitted at the last stream. This makes error handling simple
export function pipesetup(...streams) {
  return streams.reduce((src, dst) => {
    src.on('error', err => dst.emit('error', err))
    return src.pipe(dst)
  })
}

// return a Readable stream that emits data
export function readableStream(data) {
  var s = new stream.Readable()
  s._read = () => {}
  s.push(data)
  s.push(null)
  return s
}
<|endoftext|>


<commit_before>/*!
 * Различные вспомогательные методы и функции
 */

/**
 * Вернуть истинное имя директивы
 *
 * @param {?string} name - исходное имя
 * @return {?string}
 */
function getName(name) {
	return aliases[name] || name;
}

/**
 * Вернуть список названий шаблонов,
 * которые участвуют в цепи наследования указанного
 *
 * @param {string} name - имя шаблона
 * @return {!Array}
 */
function getExtList(name) {
	if (extListCache[name]) {
		return extListCache[name].slice();
	}

	var res = [];
	while (name = extMap[name]) {
		res.unshift(name);
	}

	extListCache[name] = res;
	return res.slice();
}

/**
 * Очистить кеш областей видимости заданного шаблона
 * @param {string} name - имя шаблона
 */
function clearScopeCache(name) {
	forIn(scopeCache, (cluster, key) => {
		if (key === 'template') {
			if (cluster[name] && cluster[name].parent) {
				delete cluster[name].parent.children[name];
			}

		} else {
			forIn(cluster[name], (el) => {
				if (el.parent) {
					delete el.parent.children[name];
				}
			});
		}

		delete cluster[name];
	});
}

/**
 * Вернуть имя функции из заданной строки
 *
 * @param {string} str - исходная строка
 * @param {?boolean=} [opt_empty=false] - если true, то допускается "пустое" имя
 * @return {string}
 */
DirObj.prototype.getFnName = function (str, opt_empty) {
	var tmp = /^[^(]+/.exec(str),
		val = tmp ? tmp[0].trim() : '';

	if (!opt_empty && !val) {
		this.error(`invalid "${this.name}" declaration`);
	}

	return val;
};

/**
 * Вернуть значение разницы длины команды с учётом типа декларации директивы
 *
 * @param {number} length - исходная длина
 * @return {number}
 */
DirObj.prototype.getDiff = function (length) {
	return length + Number(this.needPrfx) + 1;
};

var dirGroupCache = {};

/**
 * Клонировать заданный объект
 *
 * @param {?} obj - исходный объект
 * @return {?}
 */
function clone(obj) {
	return JSON.parse(JSON.stringify(obj));
}

/**
 * Вернуть таблицу названий директивы,
 * которые принадлежат к заданным группам
 *
 * @param {...string} names - название группы
 * @return {!Object}
 */
DirObj.prototype.getGroup = function (names) {
	var cacheKey = null,
		inline = Boolean(this.inlineIterators);

	if (JSON_SUPPORT) {
		let args = [];

		for (let i = -1; ++i < arguments.length;) {
			args.push(arguments[i]);
		}

		cacheKey = args.join();
		if (dirGroupCache[inline] && dirGroupCache[inline][cacheKey]) {
			return clone(dirGroupCache[inline][cacheKey]);
		}
	}

	var map = {},
		ignore = {};

	for (let i = -1; ++i < arguments.length;) {
		let name = arguments[i],
			group = groups[name];

		if (name === 'callback' && inline) {
			forIn(groups['inlineIterator'], (el, key) => {
				ignore[key] = true;
			});
		}

		forIn(group, (el, key) => {
			if (ignore[key]) {
				return;
			}

			map[key] = true;
		});
	}

	if (JSON_SUPPORT) {
		dirGroupCache[inline] = dirGroupCache[inline] || {};
		dirGroupCache[inline][cacheKey] = clone(map);
	}

	return map;
};

/**
 * Сбросить слой параметров компиляции
 * @return {!DirObj}
 */
DirObj.prototype.popParams = function () {
	this.params.pop();

	forIn(this.params[this.params.length - 1], (el, key) => {
		this[key] = el;
	});

	return this;
};

/**
 * Заменить %fileName% в заданной строке на имя активного файла
 *
 * @param {string} str - исходная строка
 * @return {string}
 */
DirObj.prototype.replaceFileName = function (str) {
	var file = this.info['file'],
		basename;

	str = this.replaceDangerBlocks(str.replace(/(.?)%fileName%/g, (sstr, $1) => {
		if (!file) {
			this.error('placeholder %fileName% can\'t be used without "file" option');
			return '';
		}

		if (!IS_NODE) {
			this.error('placeholder %fileName% can\'t be used with live compilation in browser');
			return '';
		}

		if (!basename) {
			let path = require('path');
			basename = path.basename(file, path.extname(file));
		}

		var str = basename;

		if ($1) {
			if ($1 !== '.') {
				str = `${$1}'${str}'`;

			} else {
				str = $1 + str;
			}
		}

		return str;
	}));

	return str;
};

var nmRgxp = /\.|\[/,
	nmssRgxp = /^\[/,
	nmsRgxp = /\[/g,
	nmeRgxp = /]/g;

/**
 * Подготовить заданную строку декларации имени шаблона
 * (вычисление выражений и т.д.)
 *
 * @param {string} name - исходная строка
 * @return {string}
 */
DirObj.prototype.prepareNameDecl = function (name) {
	name = this.replaceFileName(name);
	if (nmRgxp.test(name)) {
		let tmpArr = name
			.replace(nmssRgxp, '%')
			.replace(nmsRgxp, '.%')
			.replace(nmeRgxp, '')
			.split('.');

		let str = '',
			length = tmpArr.length;

		for (let i = -1; ++i < length;) {
			let el = tmpArr[i],
				custom = el.charAt(0) === '%';

			if (custom) {
				el = el.substring(1);
			}

			if (custom) {
				str += /* cbws */`['${
					applyDefEscape(
						this.returnEvalVal(
							this.prepareOutput(el, true)
						)
					)
				}']`;

				continue;
			}

			str += str ? `.${el}` : el;
		}

		name = str;
	}

	return name.trim();
};
<commit_msg>Удалён лишний код<commit_after>/*!
 * Различные вспомогательные методы и функции
 */

/**
 * Вернуть истинное имя директивы
 *
 * @param {?string} name - исходное имя
 * @return {?string}
 */
function getName(name) {
	return aliases[name] || name;
}

/**
 * Вернуть список названий шаблонов,
 * которые участвуют в цепи наследования указанного
 *
 * @param {string} name - имя шаблона
 * @return {!Array}
 */
function getExtList(name) {
	if (extListCache[name]) {
		return extListCache[name].slice();
	}

	var res = [];
	while (name = extMap[name]) {
		res.unshift(name);
	}

	extListCache[name] = res;
	return res.slice();
}

/**
 * Очистить кеш областей видимости заданного шаблона
 * @param {string} name - имя шаблона
 */
function clearScopeCache(name) {
	forIn(scopeCache, (cluster, key) => {
		if (key === 'template') {
			if (cluster[name] && cluster[name].parent) {
				delete cluster[name].parent.children[name];
			}

		} else {
			forIn(cluster[name], (el) => {
				if (el.parent) {
					delete el.parent.children[name];
				}
			});
		}

		delete cluster[name];
	});
}

/**
 * Вернуть имя функции из заданной строки
 *
 * @param {string} str - исходная строка
 * @param {?boolean=} [opt_empty=false] - если true, то допускается "пустое" имя
 * @return {string}
 */
DirObj.prototype.getFnName = function (str, opt_empty) {
	var tmp = /^[^(]+/.exec(str),
		val = tmp ? tmp[0].trim() : '';

	if (!opt_empty && !val) {
		this.error(`invalid "${this.name}" declaration`);
	}

	return val;
};

/**
 * Вернуть значение разницы длины команды с учётом типа декларации директивы
 *
 * @param {number} length - исходная длина
 * @return {number}
 */
DirObj.prototype.getDiff = function (length) {
	return length + Number(this.needPrfx) + 1;
};

var dirGroupCache = {};

/**
 * Клонировать заданный объект
 *
 * @param {?} obj - исходный объект
 * @return {?}
 */
function clone(obj) {
	return JSON.parse(JSON.stringify(obj));
}

/**
 * Вернуть таблицу названий директивы,
 * которые принадлежат к заданным группам
 *
 * @param {...string} names - название группы
 * @return {!Object}
 */
DirObj.prototype.getGroup = function (names) {
	var cacheKey = null,
		inline = this.inlineIterators;

	if (JSON_SUPPORT) {
		let args = [];

		for (let i = -1; ++i < arguments.length;) {
			args.push(arguments[i]);
		}

		cacheKey = args.join();
		if (dirGroupCache[inline] && dirGroupCache[inline][cacheKey]) {
			return clone(dirGroupCache[inline][cacheKey]);
		}
	}

	var map = {},
		ignore = {};

	for (let i = -1; ++i < arguments.length;) {
		let name = arguments[i],
			group = groups[name];

		if (name === 'callback' && inline) {
			forIn(groups['inlineIterator'], (el, key) => {
				ignore[key] = true;
			});
		}

		forIn(group, (el, key) => {
			if (ignore[key]) {
				return;
			}

			map[key] = true;
		});
	}

	if (JSON_SUPPORT) {
		dirGroupCache[inline] = dirGroupCache[inline] || {};
		dirGroupCache[inline][cacheKey] = clone(map);
	}

	return map;
};

/**
 * Сбросить слой параметров компиляции
 * @return {!DirObj}
 */
DirObj.prototype.popParams = function () {
	this.params.pop();

	forIn(this.params[this.params.length - 1], (el, key) => {
		this[key] = el;
	});

	return this;
};

/**
 * Заменить %fileName% в заданной строке на имя активного файла
 *
 * @param {string} str - исходная строка
 * @return {string}
 */
DirObj.prototype.replaceFileName = function (str) {
	var file = this.info['file'],
		basename;

	str = this.replaceDangerBlocks(str.replace(/(.?)%fileName%/g, (sstr, $1) => {
		if (!file) {
			this.error('placeholder %fileName% can\'t be used without "file" option');
			return '';
		}

		if (!IS_NODE) {
			this.error('placeholder %fileName% can\'t be used with live compilation in browser');
			return '';
		}

		if (!basename) {
			let path = require('path');
			basename = path.basename(file, path.extname(file));
		}

		var str = basename;

		if ($1) {
			if ($1 !== '.') {
				str = `${$1}'${str}'`;

			} else {
				str = $1 + str;
			}
		}

		return str;
	}));

	return str;
};

var nmRgxp = /\.|\[/,
	nmssRgxp = /^\[/,
	nmsRgxp = /\[/g,
	nmeRgxp = /]/g;

/**
 * Подготовить заданную строку декларации имени шаблона
 * (вычисление выражений и т.д.)
 *
 * @param {string} name - исходная строка
 * @return {string}
 */
DirObj.prototype.prepareNameDecl = function (name) {
	name = this.replaceFileName(name);
	if (nmRgxp.test(name)) {
		let tmpArr = name
			.replace(nmssRgxp, '%')
			.replace(nmsRgxp, '.%')
			.replace(nmeRgxp, '')
			.split('.');

		let str = '',
			length = tmpArr.length;

		for (let i = -1; ++i < length;) {
			let el = tmpArr[i],
				custom = el.charAt(0) === '%';

			if (custom) {
				el = el.substring(1);
			}

			if (custom) {
				str += /* cbws */`['${
					applyDefEscape(
						this.returnEvalVal(
							this.prepareOutput(el, true)
						)
					)
				}']`;

				continue;
			}

			str += str ? `.${el}` : el;
		}

		name = str;
	}

	return name.trim();
};
<|endoftext|>


<commit_before>import 'es6-promise/auto'
import Vue from 'vue'
import Meta from 'vue-meta'
import { createRouter } from './router.js'
import NoSSR from './components/no-ssr.js'
import NuxtChild from './components/nuxt-child.js'
import NuxtLink from './components/nuxt-link.js'
import NuxtError from '<%= components.ErrorPage ? components.ErrorPage : "./components/nuxt-error.vue" %>'
import Nuxt from './components/nuxt.vue'
import App from '<%= appPath %>'
import { getContext, getLocation } from './utils'
<% if (store) { %>import { createStore } from './store.js'<% } %>
<% plugins.forEach(plugin => { %>import <%= plugin.name %> from '<%= plugin.name %>'
<% }) %>

// Component: <no-ssr>
Vue.component(NoSSR.name, NoSSR)

// Component: <nuxt-child>
Vue.component(NuxtChild.name, NuxtChild)

// Component: <nuxt-link>
Vue.component(NuxtLink.name, NuxtLink)

// Component: <nuxt>`
Vue.component(Nuxt.name, Nuxt)

// vue-meta configuration
Vue.use(Meta, {
  keyName: 'head', // the component option name that vue-meta looks for meta info on.
  attribute: 'data-n-head', // the attribute name vue-meta adds to the tags it observes
  ssrAttribute: 'data-n-head-ssr', // the attribute name that lets vue-meta know that meta info has already been server-rendered
  tagIDKeyName: 'hid' // the property name that vue-meta uses to determine whether to overwrite or append a tag
})

const defaultTransition = <%=
  serialize(transition)
  .replace('beforeEnter(', 'function(').replace('enter(', 'function(').replace('afterEnter(', 'function(')
  .replace('enterCancelled(', 'function(').replace('beforeLeave(', 'function(').replace('leave(', 'function(')
  .replace('afterLeave(', 'function(').replace('leaveCancelled(', 'function(')
%>

async function createApp (ssrContext) {
  const router = createRouter()

  <% if (store) { %>const store = createStore()<% } %>

  if (process.server && ssrContext && ssrContext.url) {
    await new Promise((resolve, reject) => {
      router.push(ssrContext.url, resolve, reject)
    })
  }

  // Create Root instance
  // here we inject the router and store to all child components,
  // making them available everywhere as `this.$router` and `this.$store`.
  const app = {
    router,
    <% if(store) { %> store,<%  } %>
    _nuxt: {
      defaultTransition,
      transitions: [ defaultTransition ],
      setTransitions (transitions) {
        if (!Array.isArray(transitions)) {
          transitions = [ transitions ]
        }
        transitions = transitions.map((transition) => {
          if (!transition) {
            transition = defaultTransition
          } else if (typeof transition === 'string') {
            transition = Object.assign({}, defaultTransition, { name: transition })
          } else {
            transition = Object.assign({}, defaultTransition, transition)
          }
          return transition
        })
        this.$options._nuxt.transitions = transitions
        return transitions
      },
      err: null,
      dateErr: null,
      error (err) {
        err = err || null
        if (typeof err === 'string') {
          err = { statusCode: 500, message: err }
        }
        const _nuxt = this._nuxt || this.$options._nuxt
        _nuxt.dateErr = Date.now()
        _nuxt.err = err
        return err
      }
    },
    ...App
  }

  const next = ssrContext ? ssrContext.next : location => app.router.push(location)
  let route = router.currentRoute
  if (!ssrContext) {
    const path = getLocation(router.options.base)
    route = router.resolve(path).route
  }
  const ctx = getContext({
    isServer: !!ssrContext,
    isClient: !ssrContext,
    route,
    next,
    error: app._nuxt.error.bind(app),
    <% if(store) { %>store,<%  } %>
    req: ssrContext ? ssrContext.req : undefined,
    res: ssrContext ? ssrContext.res : undefined,
    beforeRenderFns: ssrContext ? ssrContext.beforeRenderFns : undefined
  }, app)

  <% plugins.filter(p => p.ssr).forEach(plugin => { %>
  if (typeof <%= plugin.name %> === 'function') await <%= plugin.name %>(ctx)<% }) %>
  <% if (plugins.filter(p => !p.ssr).length) { %>
  if (process.browser) { <% plugins.filter(p => !p.ssr).forEach(plugin => { %>
    if (typeof <%= plugin.name %> === 'function') await <%= plugin.name %>(ctx)<% }) %>
  }<% } %>

  <% if (store) { %>
  if (process.browser) {
    // Replace store state before calling plugins
    if (window.__NUXT__ && window.__NUXT__.state) {
      store.replaceState(window.__NUXT__.state)
    }
  }
  <% } %>

  return {
    app,
    router,
    <% if(store) { %> store <%  } %>
  }
}

export { createApp, NuxtError }
<commit_msg>fix: SSR call router.push after plugin execution<commit_after>import 'es6-promise/auto'
import Vue from 'vue'
import Meta from 'vue-meta'
import { createRouter } from './router.js'
import NoSSR from './components/no-ssr.js'
import NuxtChild from './components/nuxt-child.js'
import NuxtLink from './components/nuxt-link.js'
import NuxtError from '<%= components.ErrorPage ? components.ErrorPage : "./components/nuxt-error.vue" %>'
import Nuxt from './components/nuxt.vue'
import App from '<%= appPath %>'
import { getContext, getLocation } from './utils'
<% if (store) { %>import { createStore } from './store.js'<% } %>
<% plugins.forEach(plugin => { %>import <%= plugin.name %> from '<%= plugin.name %>'
<% }) %>

// Component: <no-ssr>
Vue.component(NoSSR.name, NoSSR)

// Component: <nuxt-child>
Vue.component(NuxtChild.name, NuxtChild)

// Component: <nuxt-link>
Vue.component(NuxtLink.name, NuxtLink)

// Component: <nuxt>`
Vue.component(Nuxt.name, Nuxt)

// vue-meta configuration
Vue.use(Meta, {
  keyName: 'head', // the component option name that vue-meta looks for meta info on.
  attribute: 'data-n-head', // the attribute name vue-meta adds to the tags it observes
  ssrAttribute: 'data-n-head-ssr', // the attribute name that lets vue-meta know that meta info has already been server-rendered
  tagIDKeyName: 'hid' // the property name that vue-meta uses to determine whether to overwrite or append a tag
})

const defaultTransition = <%=
  serialize(transition)
  .replace('beforeEnter(', 'function(').replace('enter(', 'function(').replace('afterEnter(', 'function(')
  .replace('enterCancelled(', 'function(').replace('beforeLeave(', 'function(').replace('leave(', 'function(')
  .replace('afterLeave(', 'function(').replace('leaveCancelled(', 'function(')
%>

async function createApp (ssrContext) {
  const router = createRouter()

  <% if (store) { %>const store = createStore()<% } %>

  // Create Root instance
  // here we inject the router and store to all child components,
  // making them available everywhere as `this.$router` and `this.$store`.
  const app = {
    router,
    <% if(store) { %> store,<%  } %>
    _nuxt: {
      defaultTransition,
      transitions: [ defaultTransition ],
      setTransitions (transitions) {
        if (!Array.isArray(transitions)) {
          transitions = [ transitions ]
        }
        transitions = transitions.map((transition) => {
          if (!transition) {
            transition = defaultTransition
          } else if (typeof transition === 'string') {
            transition = Object.assign({}, defaultTransition, { name: transition })
          } else {
            transition = Object.assign({}, defaultTransition, transition)
          }
          return transition
        })
        this.$options._nuxt.transitions = transitions
        return transitions
      },
      err: null,
      dateErr: null,
      error (err) {
        err = err || null
        if (typeof err === 'string') {
          err = { statusCode: 500, message: err }
        }
        const _nuxt = this._nuxt || this.$options._nuxt
        _nuxt.dateErr = Date.now()
        _nuxt.err = err
        return err
      }
    },
    ...App
  }

  const next = ssrContext ? ssrContext.next : location => app.router.push(location)
  let route
  if (ssrContext) {
    route = router.resolve(ssrContext.url).route
  } else {
    const path = getLocation(router.options.base)
    route = router.resolve(path).route
  }
  const ctx = getContext({
    isServer: !!ssrContext,
    isClient: !ssrContext,
    route,
    next,
    error: app._nuxt.error.bind(app),
    <% if(store) { %>store,<%  } %>
    req: ssrContext ? ssrContext.req : undefined,
    res: ssrContext ? ssrContext.res : undefined,
    beforeRenderFns: ssrContext ? ssrContext.beforeRenderFns : undefined
  }, app)

  <% plugins.filter(p => p.ssr).forEach(plugin => { %>
  if (typeof <%= plugin.name %> === 'function') await <%= plugin.name %>(ctx)<% }) %>
  <% if (plugins.filter(p => !p.ssr).length) { %>
  if (process.browser) { <% plugins.filter(p => !p.ssr).forEach(plugin => { %>
    if (typeof <%= plugin.name %> === 'function') await <%= plugin.name %>(ctx)<% }) %>
  }<% } %>

  <% if (store) { %>
  if (process.browser) {
    // Replace store state before calling plugins
    if (window.__NUXT__ && window.__NUXT__.state) {
      store.replaceState(window.__NUXT__.state)
    }
  }
  <% } %>

  if (process.server && ssrContext && ssrContext.url) {
    await new Promise((resolve, reject) => {
      router.push(ssrContext.url, resolve, reject)
    })
  }

  return {
    app,
    router,
    <% if(store) { %> store <%  } %>
  }
}

export { createApp, NuxtError }
<|endoftext|>


<commit_before>/* change github streak color functionality */
function updateStyle(selector, property, value) {
    [...document.querySelectorAll(selector)].forEach(node => {
        node.style[property] = value;
    });
}

function changeContributionsColor() {
    const color = localStorage.getItem('colorScheme');
    const colorSchemes = {
        'blue-sky': {
            'eeeeee': 'eeeeee',
            'd6e685': '9DC1F6',
            '8cc665': '629DF3',
            '44a340': '2B7BF2',
            '1e6823': '0363F0'
        },
        'halloween': {
            'eeeeee': 'eeeeee',
            'd6e685': 'FFEE58',
            '8cc665': 'FFCA28',
            '44a340': 'EF6C00',
            '1e6823': '000000'
        }
    };

    if (color && colorSchemes[color]) {
        Object.keys(colorSchemes[color]).forEach(key => {
            const currentColorScheme = colorSchemes[color];
            updateStyle(`rect[fill='#${key}']`, 'fill', `#${currentColorScheme[key]}`);
            updateStyle(`li[style='background-color: #${key}']`, 'backgroundColor', `#${currentColorScheme[key]}`);
        });
    }
}

module.exports = changeContributionsColor;
<commit_msg>fixed outdated colorScheme<commit_after>/* change github streak color functionality */
function updateStyle(selector, property, value) {
    [...document.querySelectorAll(selector)].forEach(node => {
        node.style[property] = value;
    });
}

function changeContributionsColor() {
    const color = localStorage.getItem('colorScheme');
    const colorSchemes = {
        'blue-sky': {
            'ebedf0': 'ebedf0',
            'c6e48b': '9DC1F6',
            '7bc96f': '629DF3',
            '239a3b': '2B7BF2',
            '196127': '0363F0'
        },
        'halloween': {
            'ebedf0': 'ebedf0',
            'c6e48b': 'FFEE58',
            '7bc96f': 'FFCA28',
            '239a3b': 'EF6C00',
            '196127': '000000'
        }
    };

    if (color && colorSchemes[color]) {
        Object.keys(colorSchemes[color]).forEach(key => {
            const currentColorScheme = colorSchemes[color];
            updateStyle(`rect[fill='#${key}']`, 'fill', `#${currentColorScheme[key]}`);
            updateStyle(`li[style='background-color: #${key}']`, 'backgroundColor', `#${currentColorScheme[key]}`);
        });
    }
}

module.exports = changeContributionsColor;
<|endoftext|>


<commit_before>/**
 * Module dependencies.
 */

var _				= require( 'lodash' ),
	EventEmitter	= require('events').EventEmitter,
	async			= require('async'),
	util			= require( '../util'),
	loadSails		= require('./load'),
	exposeGlobals	= require('./exposeGlobals'),
	runBootstrap	= require('./bootstrap'),
	Grunt			= require('../grunt');

/**
 * Expose `Sails` constructor
 */

module.exports = Sails;

/**
 * Sails constructor
 *
 * @api private
 */

function Sails () {

	/**
	 * Expose utilities
	 *
	 * @api private
	 */

	this.util = util;

	/**
	 * Load the pieces of a Sails app
	 *
	 * @api private
	 */

	this.load = loadSails(this);

	/**
	 * Start the Sails server
	 *
	 * @api private
	 */

	this.initialize = function (cb) {

		var sails = this;

		// Indicate that server is starting
		sails.log('Starting app at ' + sails.config.appPath + '...');

		// Optionally expose services, models, sails, _, async, etc. as globals
		exposeGlobals(sails)();

		// Add beforeShutdown event
		process.on('SIGINT', function() {
			beforeShutdown(process.exit);
		});
		process.on('SIGTERM', function() {
			beforeShutdown(process.exit);
		});
		process.on('exit', function() {
			if (!sails._exiting) beforeShutdown();
		});
		function beforeShutdown(cb) {
			sails._exiting = true;
			if(_.isFunction(sails.config.beforeShutdown)) {
				sails.config.beforeShutdown(cb);
			}
			else cb && cb();
		}

		// Run the app bootstrap
		runBootstrap(sails)(function (err) {
			if (err) return cb(err);

			// And fire the `ready` event
			// This is listened to by attached servers, etc.
			sails.emit('ready');

			cb && cb();
		});
	};

	/**
	 * Factory method to generate a sails instance,
	 * lift() is also the entry point for the Sails.js runtime
	 * Loads the app, then starts the server.
	 *
	 * @api public
	 */

	this.lift = function (configOverride, cb) {

		var sails = this;

		// Stow CLI/env override
		this.config = _.clone(configOverride || {});

		async.series([

			this.load,

			this.initialize

		], function sailsReady (err, results) {

			sails.log();
			sails.log.ship();
			sails.log('Sails (v'+sails.version +') lifted in ' + sails.config.environment + ' mode.');
			return cb && cb(err, sails);
		});
	};

	/**
	 * Kill the server
	 * ( Socket.io server is stopped automatically when Express server is closed )
	 *
	 * @api public
	 */

	this.lower = function (cb) {
		sails.express.server.close();
	};

	/**
	 * Run the grunt build task
	 *
	 * @api public
	 */

	this.build = function (taskName, cb) {

		// Default to 'build' task
		taskName = taskName || 'build';

		var log = this.log;
		log.info('Building assets into directory...');

		// Fire up grunt
		var grunt = Grunt(this);
		grunt(taskName, function (err) {
			if (err) return cb && cb(err);

			log.info('Successfully built \'www\' directory in the application root.');
			cb && cb();
		});
	};

	_.bindAll(this);
}

/**
 * Extend from EventEmitter to allow hooks to listen to stuff
 *
 * @api private
 */

Sails.prototype = new EventEmitter();
Sails.prototype.constructor = Sails;

// Remove memory-leak warning about max listeners
// See: http://nodejs.org/docs/latest/api/events.html#events_emitter_setmaxlisteners_n
Sails.prototype.setMaxListeners(0);

/**
 * Probably can be removed:
 *
 * @api private
 */

// Sails.prototype.after = function ( id, handler ) {

// 	// Make sure the object to track handlers exists
// 	this.__after_bindings = this.__after_bindings || {};

// 	// If the event handler has already fired, just fire it again
// 	if (this.__after_bindings[id]) {
// 		handler.apply(this, this.__after_bindings[id].toArray());
// 	}

// 	// Otherwise listen for when the event fires
// 	else {
// 		this.on(id, function () {

// 			// Fire the event handler only once
// 			if (!sails.__after_bindings[id]) {
// 				handler.apply(this, arguments.toArray());
// 			}

// 			// But remember that it's happened, so if after() is called afterwards,
// 			// the handler will be triggered each time
// 			else sails.__after_bindings[id] = arguments;
// 		});
// 	}
// };

<commit_msg>use callback in Sails.lower()<commit_after>/**
 * Module dependencies.
 */

var _				= require( 'lodash' ),
	EventEmitter	= require('events').EventEmitter,
	async			= require('async'),
	util			= require( '../util'),
	loadSails		= require('./load'),
	exposeGlobals	= require('./exposeGlobals'),
	runBootstrap	= require('./bootstrap'),
	Grunt			= require('../grunt');

/**
 * Expose `Sails` constructor
 */

module.exports = Sails;

/**
 * Sails constructor
 *
 * @api private
 */

function Sails () {

	/**
	 * Expose utilities
	 *
	 * @api private
	 */

	this.util = util;

	/**
	 * Load the pieces of a Sails app
	 *
	 * @api private
	 */

	this.load = loadSails(this);

	/**
	 * Start the Sails server
	 *
	 * @api private
	 */

	this.initialize = function (cb) {

		var sails = this;

		// Indicate that server is starting
		sails.log('Starting app at ' + sails.config.appPath + '...');

		// Optionally expose services, models, sails, _, async, etc. as globals
		exposeGlobals(sails)();

		// Add beforeShutdown event
		process.on('SIGINT', function() {
			beforeShutdown(process.exit);
		});
		process.on('SIGTERM', function() {
			beforeShutdown(process.exit);
		});
		process.on('exit', function() {
			if (!sails._exiting) beforeShutdown();
		});
		function beforeShutdown(cb) {
			sails._exiting = true;
			if(_.isFunction(sails.config.beforeShutdown)) {
				sails.config.beforeShutdown(cb);
			}
			else cb && cb();
		}

		// Run the app bootstrap
		runBootstrap(sails)(function (err) {
			if (err) return cb(err);

			// And fire the `ready` event
			// This is listened to by attached servers, etc.
			sails.emit('ready');

			cb && cb();
		});
	};

	/**
	 * Factory method to generate a sails instance,
	 * lift() is also the entry point for the Sails.js runtime
	 * Loads the app, then starts the server.
	 *
	 * @api public
	 */

	this.lift = function (configOverride, cb) {

		var sails = this;

		// Stow CLI/env override
		this.config = _.clone(configOverride || {});

		async.series([

			this.load,

			this.initialize

		], function sailsReady (err, results) {

			sails.log();
			sails.log.ship();
			sails.log('Sails (v'+sails.version +') lifted in ' + sails.config.environment + ' mode.');
			return cb && cb(err, sails);
		});
	};

	/**
	 * Kill the server
	 * ( Socket.io server is stopped automatically when Express server is closed )
	 *
	 * @api public
	 */

	this.lower = function (cb) {
		sails.express.server.close(cb);
	};

	/**
	 * Run the grunt build task
	 *
	 * @api public
	 */

	this.build = function (taskName, cb) {

		// Default to 'build' task
		taskName = taskName || 'build';

		var log = this.log;
		log.info('Building assets into directory...');

		// Fire up grunt
		var grunt = Grunt(this);
		grunt(taskName, function (err) {
			if (err) return cb && cb(err);

			log.info('Successfully built \'www\' directory in the application root.');
			cb && cb();
		});
	};

	_.bindAll(this);
}

/**
 * Extend from EventEmitter to allow hooks to listen to stuff
 *
 * @api private
 */

Sails.prototype = new EventEmitter();
Sails.prototype.constructor = Sails;

// Remove memory-leak warning about max listeners
// See: http://nodejs.org/docs/latest/api/events.html#events_emitter_setmaxlisteners_n
Sails.prototype.setMaxListeners(0);

/**
 * Probably can be removed:
 *
 * @api private
 */

// Sails.prototype.after = function ( id, handler ) {

// 	// Make sure the object to track handlers exists
// 	this.__after_bindings = this.__after_bindings || {};

// 	// If the event handler has already fired, just fire it again
// 	if (this.__after_bindings[id]) {
// 		handler.apply(this, this.__after_bindings[id].toArray());
// 	}

// 	// Otherwise listen for when the event fires
// 	else {
// 		this.on(id, function () {

// 			// Fire the event handler only once
// 			if (!sails.__after_bindings[id]) {
// 				handler.apply(this, arguments.toArray());
// 			}

// 			// But remember that it's happened, so if after() is called afterwards,
// 			// the handler will be triggered each time
// 			else sails.__after_bindings[id] = arguments;
// 		});
// 	}
// };

<|endoftext|>


<commit_before>var Data = {

	questMatrix: function() {
		if (!Data.questArray) {
			var questArray = [
				{'questName':'Orientation', 'level':1, 'location':'Initialize (Stage 1)'},
				{'questName':'Fist Fighter', 'level':1, 'location':'Initialize (Stage 2)'},
				{'questName':'Suiting Up', 'level':1, 'location':'Initialize (Stage 2)'},
				{'questName':'Crawling Corruption', 'level':2, 'location':'Data Store'},
				{'questName':'Energy Leak', 'level':2, 'location':'Data Store'},
				{'questName':'Access Alert', 'level':2, 'location':'Databank Beta'},
				{'questName':'System Error', 'level':3, 'location':'Security Core'},
				{'questName':'Powered Down', 'level':4, 'location':'Analytical Layer'},
				{'questName':'Bit Builder', 'level':5, 'location':'System Edge'},
				{'questName':'Facility Assault', 'level':5, 'location':'Transfer Pod'},
				{'questName':'Delivery Note', 'level':8, 'location':'Cloning Facility (Loading Bay)'},
				{'questName':'Resource Stripping', 'level':7, 'location':'Cloning Facility (East Wing)'},
				{'questName':'Call to Arms', 'level':10, 'location':'Desert Path (Straights)'},
				{'questName':'New Blood', 'level':10, 'location':'Desert Path (Straights)'},
				{'questName':'Poison Desire', 'level':12, 'location':'Desert Path (Steps)'},
				{'questName':'Droid Delivery', 'level':15, 'location':'Highridge (Descent)'},
				{'questName':'Way of the Old', 'level':16, 'location':'Phantom Lake (Shore)'},
				{'questName':'Tribal Assault', 'level':16, 'location':'Taulin City'},
				{'questName':'Stolen Labour', 'level':19, 'location':'Taulin Outskirts (Edge)'},
				{'questName':'Assimilation', 'level':20, 'location':'Taulin Outskirts (Dunes)'},
				{'questName':'Settlement Defense', 'level':22, 'location':'Taulin Gamma Wastes (Straights)'},
				{'questName':'Down Lines', 'level':25, 'location':'Taulin Gamma Wastes (Plateau)'},
				{'questName':'Revenge of the G27\'s', 'level':26, 'location':'Taulin Gamma Wastes (Towers)'},
				{'questName':'Desiccator Prototype', 'level':28, 'location':'Taulin Gamma Wastes (Sands)'},
				{'questName':'Money from the Mines', 'level':29, 'location':'Higridge Mines (Mouth)'},
				{'questName':'Hiding from the Hand', 'level':34, 'location':'Highridge Mines (Rock Layer)'},
				{'questName':'Miner Dissent', 'level':36, 'location':'Highridge Mines (Volcanic Deposits)'},
				{'questName':'Threat from the Shadows', 'level':38, 'location':'Highridge Mines (Sprawl)'},
				{'questName':'Toxic Rupture', 'level':39, 'location':'Highridge Mines (Dark Excavations)'},
				{'questName':'Berserker Bots!', 'level':40, 'location':'Highridge Mines (Unstable Layer)'},
				{'questName':'Escaping the Mines', 'level':40, 'location':'Mining Facility'},
				{'questName':'Young Warrior', 'level':41, 'location':'Highridge Crag (Deserted Camp)'},
				{'questName':'Snatched Notes', 'level':43, 'location':'Highridge Crag (Upper Slopes)'},
				{'questName':'Bomb Disposal', 'level':45, 'location':'Highridge Crag (Yarn Domain)'},
				{'questName':'Revenge', 'level':45, 'location':'Highridge Crag (Vale)'},
				{'questName':'The Antidote', 'level':45, 'location':'Highridge Crag (Yarn Retreat)'},
				{'questName':'Wild Tales', 'level':45, 'location':'Highridge Crag (Shard Gate)'},
				{'questName':'Elders Request', 'level':51, 'location':'Amethyst Peak (Base)'},
				{'questName':'Crystalline Pollution', 'level':54, 'location':'Amethyst Peak (Lower Slope)'},
				{'questName':'Seek and Retrieve', 'level':56, 'location':'Amethyst Peak (Upper Slope)'},
				{'questName':'Crystal Gathers', 'level':58, 'location':'Amethyst Peak (Climb)'},
				{'questName':'Stemming the Tide', 'level':59, 'location':'Amethyst Peak (View)'},
				{'questName':'Power Hunger', 'level':60, 'location':'Amethyst Peak (Pinnacle)'}
			];
			Data.questArray = questArray.sort();
		}
		return Data.questArray;
	},

	plantFromComponent: function(aComponent) {
		switch(aComponent) {
			case "Amber Essense": return "Amber Plant"; break;
			case "Blood Bloom Flower": return "Blood Bloom Plant"; break;
			case "Dark Shade ": return "Dark Shade Plant"; break;
			case "Snake Eye": return "Elya Snake Head"; break;
			case "Snake Venom Fang": return "Elya Snake Head"; break;
			case "Heffle Wart": return "Heffle Wart Plant"; break;
			case "Jademare Blossom": return "Jademare Plant"; break;
			case "Trinettle Leaf": return "Trinettle Plant"; break;
			case "Purplet Flower": return "Purplet Plant"; break;
			default: return aComponent;
		}
	},

	potionList: function() {
		if (!Data.potionArray) {
			Data.potionArray=[
					{"searchname":"Potion of the Wise",         "shortname":"Lib 200",   "buff":"Librarian",      "level":200,  "duration":120, "minlevel":5, "bound":true},
					{"searchname":"Potion of the Bookworm",     "shortname":"Lib 225",   "buff":"Librarian",      "level":225,  "duration":90,  "minlevel":5},
					{"searchname":"Potion of Shattering",       "shortname":"SA",        "buff":"Shatter Armor",  "level":150,  "duration":20,  "minlevel":5, "bound":true},
					{"searchname":"Dragons Blood Potion",       "shortname":"ZK 200",    "buff":"Berzerk",        "level":200,  "duration":30,  "minlevel":5, "bound":true},
					{"searchname":"Berserkers Potion",          "shortname":"ZK 300",    "buff":"Berserk",        "level":300,  "duration":45,  "minlevel":5, "bound":true},
					{"searchname":"Potion of Fury",             "shortname":"ZK 350",    "buff":"Berserk",        "level":350,  "duration":60,  "minlevel":5},
					{"searchname":"Sludge Brew",                "shortname":"DC 200",    "buff":"Dark Curse",     "level":200,  "duration":45,  "minlevel":5, "bound":true},
					{"searchname":"Potion of Black Death",      "shortname":"DC 225",    "buff":"Dark Curse",     "level":225,  "duration":60,  "minlevel":5},
					{"searchname":"Potion of Aid",              "shortname":"Assist",    "buff":"Assist",         "level":150,  "duration":30,  "minlevel":5, "bound":true},
					{"searchname":"Potion of Supreme Doubling", "shortname":"DB 450",    "buff":"Doubler",        "level":450,  "duration":00,  "minlevel":5, "bound":true},
					{"searchname":"Potion of Acceleration",     "shortname":"DB 500",    "buff":"Doubler",        "level":500,  "duration":120, "minlevel":5},
					{"searchname":"Potion of Lesser Death Dealer",  "shortname":"DD",    "buff":"Death Dealer",   "level":25,   "duration":45,  "minlevel":20},
					{"searchname":"Runic Potion",               "shortname":"FI 250",    "buff":"Find Item",      "level":250,  "duration":60,  "minlevel":5, "bound":true},
					{"searchname":"Potion of Supreme Luck",     "shortname":"FI 1k",     "buff":"Find Item",      "level":1000, "duration":60,  "minlevel":5, "bound":true},
					{"searchname":"Potion of Truth",            "shortname":"EW 1k",     "buff":"Enchant Weapon", "level":1000, "duration":90,  "minlevel":5, "bound":true},
					{"searchname":"Dull Edge",                  "shortname":"DE 25",     "buff":"Dull Edge",      "level":25,   "duration":60,  "minlevel":1},
					{"searchname":"Notched Blade",              "shortname":"DE 80",     "buff":"Dull Edge",      "level":80,   "duration":45,  "minlevel":10, "bound":true},
					{"searchname":"Potion of Death",            "shortname":"DW 125",    "buff":"Death Wish",     "level":125,  "duration":15,  "minlevel":5, "bound":true},
					{"searchname":"Potion of Decay",            "shortname":"WI 150",    "buff":"Wither",         "level":150,  "duration":15,  "minlevel":5, "bound":true},
					{"searchname":"Potion of Fatality",         "shortname":"WI 350",    "buff":"Wither",         "level":350,  "duration":90,  "minlevel":10, "bound":true},
					{"searchname":"Potion of Annihilation",     "shortname":"DW 150",    "buff":"Death Wish",     "level":150,  "duration":30,  "minlevel":5}
				];
		}
		return Data.potionArray;
	}

}<commit_msg>SS2 quest update<commit_after>var Data = {

	questMatrix: function() {
		if (!Data.questArray) {
			var questArray = [
				{'questName':'Orientation', 'level':1, 'location':'Initialize (Stage 1)'},
				{'questName':'Fist Fighter', 'level':1, 'location':'Initialize (Stage 2)'},
				{'questName':'Suiting Up', 'level':1, 'location':'Initialize (Stage 2)'},
				{'questName':'Crawling Corruption', 'level':2, 'location':'Data Store'},
				{'questName':'Energy Leak', 'level':2, 'location':'Data Store'},
				{'questName':'Access Alert', 'level':2, 'location':'Databank Beta'},
				{'questName':'System Error', 'level':3, 'location':'Security Core'},
				{'questName':'Powered Down', 'level':4, 'location':'Analytical Layer'},
				{'questName':'Bit Builder', 'level':5, 'location':'System Edge'},
				{'questName':'Facility Assault', 'level':5, 'location':'Transfer Pod'},
				{'questName':'Delivery Note', 'level':8, 'location':'Cloning Facility (Loading Bay)'},
				{'questName':'Resource Stripping', 'level':7, 'location':'Cloning Facility (East Wing)'},
				{'questName':'Call to Arms', 'level':10, 'location':'Desert Path (Straights)'},
				{'questName':'New Blood', 'level':10, 'location':'Desert Path (Straights)'},
				{'questName':'Poison Desire', 'level':12, 'location':'Desert Path (Steps)'},
				{'questName':'Droid Delivery', 'level':15, 'location':'Highridge (Descent)'},
				{'questName':'Way of the Old', 'level':16, 'location':'Phantom Lake (Shore)'},
				{'questName':'Tribal Assault', 'level':16, 'location':'Taulin City'},
				{'questName':'Stolen Labour', 'level':19, 'location':'Taulin Outskirts (Edge)'},
				{'questName':'Assimilation', 'level':20, 'location':'Taulin Outskirts (Dunes)'},
				{'questName':'Settlement Defense', 'level':22, 'location':'Taulin Gamma Wastes (Straights)'},
				{'questName':'Down Lines', 'level':25, 'location':'Taulin Gamma Wastes (Plateau)'},
				{'questName':'Revenge of the G27\'s', 'level':26, 'location':'Taulin Gamma Wastes (Towers)'},
				{'questName':'Desiccator Prototype', 'level':28, 'location':'Taulin Gamma Wastes (Sands)'},
				{'questName':'Money from the Mines', 'level':29, 'location':'Higridge Mines (Mouth)'},
				{'questName':'Hiding from the Hand', 'level':34, 'location':'Highridge Mines (Rock Layer)'},
				{'questName':'Miner Dissent', 'level':36, 'location':'Highridge Mines (Volcanic Deposits)'},
				{'questName':'Threat from the Shadows', 'level':38, 'location':'Highridge Mines (Sprawl)'},
				{'questName':'Toxic Rupture', 'level':39, 'location':'Highridge Mines (Dark Excavations)'},
				{'questName':'Berserker Bots!', 'level':40, 'location':'Highridge Mines (Unstable Layer)'},
				{'questName':'Escaping the Mines', 'level':40, 'location':'Mining Facility'},
				{'questName':'Young Warrior', 'level':41, 'location':'Highridge Crag (Deserted Camp)'},
				{'questName':'Snatched Notes', 'level':43, 'location':'Highridge Crag (Upper Slopes)'},
				{'questName':'Bomb Disposal', 'level':45, 'location':'Highridge Crag (Yarn Domain)'},
				{'questName':'Revenge', 'level':45, 'location':'Highridge Crag (Vale)'},
				{'questName':'The Antidote', 'level':45, 'location':'Highridge Crag (Yarn Retreat)'},
				{'questName':'Wild Tales', 'level':45, 'location':'Highridge Crag (Shard Gate)'},
				{'questName':'Elders Request', 'level':51, 'location':'Amethyst Peak (Base)'},
				{'questName':'Crystalline Pollution', 'level':54, 'location':'Amethyst Peak (Lower Slope)'},
				{'questName':'Seek and Retrieve', 'level':56, 'location':'Amethyst Peak (Upper Slope)'},
				{'questName':'Crystal Gathers', 'level':58, 'location':'Amethyst Peak (Climb)'},
				{'questName':'Stemming the Tide', 'level':60, 'location':'Amethyst Peak (View)'},
				{'questName':'Power Hunger', 'level':60, 'location':'Amethyst Peak (Pinnacle)'}
			];
			Data.questArray = questArray.sort();
		}
		return Data.questArray;
	},

	plantFromComponent: function(aComponent) {
		switch(aComponent) {
			case "Amber Essense": return "Amber Plant"; break;
			case "Blood Bloom Flower": return "Blood Bloom Plant"; break;
			case "Dark Shade ": return "Dark Shade Plant"; break;
			case "Snake Eye": return "Elya Snake Head"; break;
			case "Snake Venom Fang": return "Elya Snake Head"; break;
			case "Heffle Wart": return "Heffle Wart Plant"; break;
			case "Jademare Blossom": return "Jademare Plant"; break;
			case "Trinettle Leaf": return "Trinettle Plant"; break;
			case "Purplet Flower": return "Purplet Plant"; break;
			default: return aComponent;
		}
	},

	potionList: function() {
		if (!Data.potionArray) {
			Data.potionArray=[
					{"searchname":"Potion of the Wise",         "shortname":"Lib 200",   "buff":"Librarian",      "level":200,  "duration":120, "minlevel":5, "bound":true},
					{"searchname":"Potion of the Bookworm",     "shortname":"Lib 225",   "buff":"Librarian",      "level":225,  "duration":90,  "minlevel":5},
					{"searchname":"Potion of Shattering",       "shortname":"SA",        "buff":"Shatter Armor",  "level":150,  "duration":20,  "minlevel":5, "bound":true},
					{"searchname":"Dragons Blood Potion",       "shortname":"ZK 200",    "buff":"Berzerk",        "level":200,  "duration":30,  "minlevel":5, "bound":true},
					{"searchname":"Berserkers Potion",          "shortname":"ZK 300",    "buff":"Berserk",        "level":300,  "duration":45,  "minlevel":5, "bound":true},
					{"searchname":"Potion of Fury",             "shortname":"ZK 350",    "buff":"Berserk",        "level":350,  "duration":60,  "minlevel":5},
					{"searchname":"Sludge Brew",                "shortname":"DC 200",    "buff":"Dark Curse",     "level":200,  "duration":45,  "minlevel":5, "bound":true},
					{"searchname":"Potion of Black Death",      "shortname":"DC 225",    "buff":"Dark Curse",     "level":225,  "duration":60,  "minlevel":5},
					{"searchname":"Potion of Aid",              "shortname":"Assist",    "buff":"Assist",         "level":150,  "duration":30,  "minlevel":5, "bound":true},
					{"searchname":"Potion of Supreme Doubling", "shortname":"DB 450",    "buff":"Doubler",        "level":450,  "duration":00,  "minlevel":5, "bound":true},
					{"searchname":"Potion of Acceleration",     "shortname":"DB 500",    "buff":"Doubler",        "level":500,  "duration":120, "minlevel":5},
					{"searchname":"Potion of Lesser Death Dealer",  "shortname":"DD",    "buff":"Death Dealer",   "level":25,   "duration":45,  "minlevel":20},
					{"searchname":"Runic Potion",               "shortname":"FI 250",    "buff":"Find Item",      "level":250,  "duration":60,  "minlevel":5, "bound":true},
					{"searchname":"Potion of Supreme Luck",     "shortname":"FI 1k",     "buff":"Find Item",      "level":1000, "duration":60,  "minlevel":5, "bound":true},
					{"searchname":"Potion of Truth",            "shortname":"EW 1k",     "buff":"Enchant Weapon", "level":1000, "duration":90,  "minlevel":5, "bound":true},
					{"searchname":"Dull Edge",                  "shortname":"DE 25",     "buff":"Dull Edge",      "level":25,   "duration":60,  "minlevel":1},
					{"searchname":"Notched Blade",              "shortname":"DE 80",     "buff":"Dull Edge",      "level":80,   "duration":45,  "minlevel":10, "bound":true},
					{"searchname":"Potion of Death",            "shortname":"DW 125",    "buff":"Death Wish",     "level":125,  "duration":15,  "minlevel":5, "bound":true},
					{"searchname":"Potion of Decay",            "shortname":"WI 150",    "buff":"Wither",         "level":150,  "duration":15,  "minlevel":5, "bound":true},
					{"searchname":"Potion of Fatality",         "shortname":"WI 350",    "buff":"Wither",         "level":350,  "duration":90,  "minlevel":10, "bound":true},
					{"searchname":"Potion of Annihilation",     "shortname":"DW 150",    "buff":"Death Wish",     "level":150,  "duration":30,  "minlevel":5}
				];
		}
		return Data.potionArray;
	}

}<|endoftext|>


<commit_before>/*

MIT License

Copyright (c) 2016 Judd Niemann

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

*/

// chessdiagram.js : defines Chess Diagram Component

import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import Board from './board.js';
import Piece from './piece.js';
import standardPieceDefinitions from './pieceDefinitions.js';

/** Chessdiagram : draws a chess diagram consisting of a board and pieces, using svg graphics */
class Chessdiagram extends Component {
	constructor(props) {
		super(props);
		this.state = {
			selectedSquare: null,
			selectedPieceType: null,
			dragX: 0,
			dragY: 0,
			isDragging: false,
			left: 0,
			top: 0,
			width: 0,
			height: 0,
		};
	}

	// Lifecycle events ////

	componentDidMount() {
		this._getClientPos();
		// add DOM events
		addEventListener('resize', this._onResize.bind(this)); // resize event not provided by React events; use DOM version
		addEventListener('scroll', this._onScroll.bind(this));
	}

	componentWillUnmount() {
		removeEventListener('resize', this._onResize.bind(this));
		removeEventListener('scroll', this._onScroll.bind(this));
	}

	componentWillReceiveProps (nextProps) {
		if ( /* changes which have an effect on coordinates */
			nextProps.squareSize !== this.props.squareSize ||
			nextProps.ranks !== this.props.ranks ||
			nextProps.files !== this.props.files
		) {
			let evt = new Event('resize');
			dispatchEvent(evt); // synthetically trigger resize event. (Can't get coords in here, because component not rendered yet ...)
		}
	}

	// event handling ////

	// DOM events
	_onResize() {
		this._getClientPos();
	}

	_onScroll() {
		this._getClientPos();
	}

	// react events
	_onMouseDown(evt) { // react event
		evt.preventDefault();
		let x = evt.clientX - this.state.left;
		let y = evt.clientY - this.state.top;
		this._grab(x,y);
	}

	_onTouchStart(evt) {
		evt.preventDefault();
		let x = evt.touches[0].clientX - this.state.left;
		let y = evt.touches[0].clientY - this.state.top;
		this._grab(x,y);
	}

	_onMouseMove(evt) {
		evt.preventDefault();
		let x = evt.clientX - this.state.left;
		let y = evt.clientY - this.state.top;
		this._move(x,y);
	}

	_onTouchMove(evt) {
		evt.preventDefault();
		let x = evt.touches[0].clientX - this.state.left;
		let y = evt.touches[0].clientY - this.state.top;
		this._move(x,y);
	}

	_onMouseUp(evt) {
		evt.preventDefault();
		let x = evt.clientX - this.state.left;
		let y = evt.clientY - this.state.top;
		this._release(x,y);
	}

	_onTouchEnd(evt) {
		evt.preventDefault();
		/* // Note: android doesn't populate touches array on touchend
		let x = evt.touches[0].clientX - this.state.left;
		let y = evt.touches[0].clientY - this.state.top;
		*/
		let [x,y] = [this.state.dragX, this.state.dragY];

		this._release(x,y);
	}

	// coordinate conversion functions ////

	_squareToCoords(square) { // convert a square name (eg 'e4') to coordinates
		if(this.props.flip) {
			let x = this.props.squareSize * (this.props.files - (square.toLowerCase().charCodeAt(0)-97));
			let y = (Number(square.slice(1))-1) * this.props.squareSize;
			return [x,y];
		} else {
			let x = this.props.squareSize * (1 + square.toLowerCase().charCodeAt(0)-97);
			let y = (this.props.ranks-Number(square.slice(1))) * this.props.squareSize;
			return [x,y];
		}
	}

	_fileRankToCoords(file, rank) { // convert zero-based file and rank values to coordinates
		if(this.props.flip) {
			let	x = this.props.squareSize * (this.props.files - file);
			let y = this.props.squareSize * rank;
			return [x,y];
		} else {
			let	x = this.props.squareSize * (1 + file);
			let y = this.props.squareSize * (this.props.ranks - rank -1);
			return [x,y];
		}
	}

	_coordsToSquare(x,y) { // convert coordinates to square name (eg e4)
		if(this.props.flip) {
			let file = String.fromCharCode(97 + this.props.files - x / this.props.squareSize + 1);
			let rank = 1 + Math.floor(y / this.props.squareSize);
			return file + rank;
		} else {
			let file = String.fromCharCode(97 + x / this.props.squareSize - 1);
			let rank = 1 + Math.floor((this.props.ranks * this.props.squareSize - y) / this.props.squareSize);
			return file + rank;
		}
	}

	// private actions

	_grab(x,y) {
		let boardW = this.props.squareSize * (1+this.props.files);
		let boardH = this.props.squareSize * (this.props.ranks);
		if(x < this.props.squareSize || x > boardW || y < 0 || y > boardH) {
			//outside the board ...
			return false;
		}
		let selectedSquare = this._coordsToSquare(x,y);
		let selectedPiece = this._getPieceAtSquare(selectedSquare);

		this.setState({
			selectedSquare: selectedSquare,
			selectedPieceType: selectedPiece ? selectedPiece.pieceType : null,
			dragX: selectedPiece ? selectedPiece.x + this.props.squareSize / 2: this.state.dragX,
			dragY: selectedPiece ? selectedPiece.y + this.props.squareSize / 2: this.state.dragY,
			isDragging: true
		});

		if(this.props.onSelectSquare) {
			this.props.onSelectSquare(selectedSquare);
		}
	}

	_move(x, y) {
		if(this.state.isDragging) {
			this.setState({dragX: x, dragY: y});
		}
	}

	_release(x,y) {
		this.setState({isDragging: false});
		let finalSquare = this._coordsToSquare(x,y);
		if(finalSquare !== this.state.selectedSquare) {
			if(this.props.onMovePiece) { // call the callback fn
				this.props.onMovePiece(this.state.selectedPieceType, this.state.selectedSquare, finalSquare);
			}
			this.setState({selectedSquare: null});
			return;
		}
	}

	// self-enquiry ////

	_getClientPos() {
		let rect = ReactDOM.findDOMNode(this).getBoundingClientRect();
		this.setState({left: rect.left, top: rect.top, width: rect.width, height: rect.height});
	}

	_getPieces() {
		if(!this.props.pieces)
			return [];

		return this.props.pieces.map((pieceString) => {
			let [pieceType, square ] = pieceString.split('@',2);	// split 'piece@square' into pieceType, square
			if(!square)
				return {pieceType: 'invalid', square: 'none', x: 0,y: 0}; // guard against nonsense input
			let [x,y] = this._squareToCoords(square);
			if (isNaN(y))
				return {pieceType: 'invalid', square: 'none', x: 0,y: 0}; // invalid y-coordinate
			return {pieceType: pieceType, square: square.toLowerCase(), x: x, y: y};
		});
	}

	_getPiecesFromFEN() {
		let pieces = [];
		let fields = this.props.fen.split(" ", 6);
		let rank=this.props.ranks-1, file = 0; // (zero-based)
		let x,y,square;
		const pieceDefinitions = Object.assign(standardPieceDefinitions, this.props.pieceDefinitions);
		const pieceChars = new RegExp('[' + Object.keys(pieceDefinitions).join('') + ']');
		for (let i = 0; i<fields[0].length; i++) {
			let c = fields[0].charAt(i);
			if(pieceChars.test(c)) {
				[x,y] = this._fileRankToCoords(file, rank);
				square = String.fromCharCode(97 + file) + (rank + 1).toString();
				pieces.push({pieceType: c, square: square, x: x, y: y});
				file++;
			} else if (c === "/") {
				rank -= 1;
				file = 0;
			}	else if(/[1-9]/.test(c)) {
				file += Number(c);
			}
		}
		return pieces;
	}

	_getPieceAtSquare(square) {
		let pieces = this.props.fen ? this._getPiecesFromFEN() : this._getPieces();
		return pieces.filter(pieceLocation => pieceLocation.square === square)[0];
	}

	// render function

	render() {
		let pieces = this.props.fen ? this._getPiecesFromFEN() : this._getPieces();
		const pieceDefinitions = Object.assign(standardPieceDefinitions, this.props.pieceDefinitions);
		return (
				<svg
					width={this.props.width === "auto" ? (1 + this.props.files) * this.props.squareSize : this.props.width}
					height={this.props.height === "auto" ? (1 + this.props.ranks) * this.props.squareSize : this.props.height}
					onMouseDown={this._onMouseDown.bind(this)}
					onTouchStart={this._onTouchStart.bind(this)}
					onMouseMove={this._onMouseMove.bind(this)}
					onTouchMove={this._onTouchMove.bind(this)}
					onMouseUp={this._onMouseUp.bind(this)}
					onTouchEnd={this._onTouchEnd.bind(this)}
				>

					<Board
						squareSize={this.props.squareSize} ranks={this.props.ranks} files={this.props.files} selectedSquare={this.state.selectedSquare}
						lightSquareColor={this.props.lightSquareColor} darkSquareColor={this.props.darkSquareColor} flip={!!this.props.flip}
					/>

					{pieces.map((piece, i) =>
						<Piece
							x={this.state.isDragging && piece.square === this.state.selectedSquare ? this.state.dragX - this.props.squareSize / 2 : piece.x}
							y={this.state.isDragging && piece.square === this.state.selectedSquare ? this.state.dragY - this.props.squareSize / 2 : piece.y}
							key={i} pieceType={piece.pieceType} squareSize={this.props.squareSize}
							drawPiece={pieceDefinitions[piece.pieceType]}
						/>
					)}

				</svg>
		);
	}
}

Chessdiagram.propTypes = {
	squareSize: React.PropTypes.number,
	ranks: React.PropTypes.number,
	files: React.PropTypes.number,
	lightSquareColor: React.PropTypes.string,
	darkSquareColor: React.PropTypes.string,
	/** if true, rotates the board so that Black pawns are moving up, and White pawns are moving down the board */
	flip: React.PropTypes.bool,
	/** callback function which is called when user moves a piece. Passes pieceType, initialSquare, finalSquare as parameters to callback */
	onMovePiece: React.PropTypes.func,
	/** callback function which is called when user clicks on a square. Passes name of square as parameter to callback */
	onSelectSquare: React.PropTypes.func,
	/** width of main svg container in pixels. If setting this manually, it should be at least 9 * squareSize to fit board AND labels*/
	width: React.PropTypes.oneOfType([
		React.PropTypes.string,
		React.PropTypes.number,
	]),
	/** height of main svg container in pixels. If setting this manually, it should be at least 9 * squareSize to fit board AND labels*/
	height: React.PropTypes.oneOfType([
		React.PropTypes.string,
		React.PropTypes.number,
	]),

	/** Chess position in FEN format (Forsyth-Edwards Notation). eg "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1" */
	fen: React.PropTypes.string,

	/** array of pieces at particular squares (alternative to fen) eg ['P@f2','P@g2','P@h2','K@g1']
	 * This format may be more suitable for unconventional board dimensions, for which standard FEN would not work
	 * Note: If both fen and pieces props are present, fen will take precedence */
	pieces: React.PropTypes.array,
	/** Optional associative array containing non-standard chess characters
	*/
	pieceDefinitions: React.PropTypes.object,
};

Chessdiagram.defaultProps = {
	width: 'auto',
	height: 'auto',
	squareSize: 45,
	ranks: 8,
	files: 8,
	lightSquareColor: "#2492FF",
	darkSquareColor:  "#005EBB",
	flip: false,
	pieceDefinitions: {},
};

export default Chessdiagram;
<commit_msg>construct regex properly<commit_after>/*

MIT License

Copyright (c) 2016 Judd Niemann

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

*/

// chessdiagram.js : defines Chess Diagram Component

import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import Board from './board.js';
import Piece from './piece.js';
import standardPieceDefinitions from './pieceDefinitions.js';

/** Chessdiagram : draws a chess diagram consisting of a board and pieces, using svg graphics */
class Chessdiagram extends Component {
	constructor(props) {
		super(props);
		this.state = {
			selectedSquare: null,
			selectedPieceType: null,
			dragX: 0,
			dragY: 0,
			isDragging: false,
			left: 0,
			top: 0,
			width: 0,
			height: 0,
		};
	}

	// Lifecycle events ////

	componentDidMount() {
		this._getClientPos();
		// add DOM events
		addEventListener('resize', this._onResize.bind(this)); // resize event not provided by React events; use DOM version
		addEventListener('scroll', this._onScroll.bind(this));
	}

	componentWillUnmount() {
		removeEventListener('resize', this._onResize.bind(this));
		removeEventListener('scroll', this._onScroll.bind(this));
	}

	componentWillReceiveProps (nextProps) {
		if ( /* changes which have an effect on coordinates */
			nextProps.squareSize !== this.props.squareSize ||
			nextProps.ranks !== this.props.ranks ||
			nextProps.files !== this.props.files
		) {
			let evt = new Event('resize');
			dispatchEvent(evt); // synthetically trigger resize event. (Can't get coords in here, because component not rendered yet ...)
		}
	}

	// event handling ////

	// DOM events
	_onResize() {
		this._getClientPos();
	}

	_onScroll() {
		this._getClientPos();
	}

	// react events
	_onMouseDown(evt) { // react event
		evt.preventDefault();
		let x = evt.clientX - this.state.left;
		let y = evt.clientY - this.state.top;
		this._grab(x,y);
	}

	_onTouchStart(evt) {
		evt.preventDefault();
		let x = evt.touches[0].clientX - this.state.left;
		let y = evt.touches[0].clientY - this.state.top;
		this._grab(x,y);
	}

	_onMouseMove(evt) {
		evt.preventDefault();
		let x = evt.clientX - this.state.left;
		let y = evt.clientY - this.state.top;
		this._move(x,y);
	}

	_onTouchMove(evt) {
		evt.preventDefault();
		let x = evt.touches[0].clientX - this.state.left;
		let y = evt.touches[0].clientY - this.state.top;
		this._move(x,y);
	}

	_onMouseUp(evt) {
		evt.preventDefault();
		let x = evt.clientX - this.state.left;
		let y = evt.clientY - this.state.top;
		this._release(x,y);
	}

	_onTouchEnd(evt) {
		evt.preventDefault();
		/* // Note: android doesn't populate touches array on touchend
		let x = evt.touches[0].clientX - this.state.left;
		let y = evt.touches[0].clientY - this.state.top;
		*/
		let [x,y] = [this.state.dragX, this.state.dragY];

		this._release(x,y);
	}

	// coordinate conversion functions ////

	_squareToCoords(square) { // convert a square name (eg 'e4') to coordinates
		if(this.props.flip) {
			let x = this.props.squareSize * (this.props.files - (square.toLowerCase().charCodeAt(0)-97));
			let y = (Number(square.slice(1))-1) * this.props.squareSize;
			return [x,y];
		} else {
			let x = this.props.squareSize * (1 + square.toLowerCase().charCodeAt(0)-97);
			let y = (this.props.ranks-Number(square.slice(1))) * this.props.squareSize;
			return [x,y];
		}
	}

	_fileRankToCoords(file, rank) { // convert zero-based file and rank values to coordinates
		if(this.props.flip) {
			let	x = this.props.squareSize * (this.props.files - file);
			let y = this.props.squareSize * rank;
			return [x,y];
		} else {
			let	x = this.props.squareSize * (1 + file);
			let y = this.props.squareSize * (this.props.ranks - rank -1);
			return [x,y];
		}
	}

	_coordsToSquare(x,y) { // convert coordinates to square name (eg e4)
		if(this.props.flip) {
			let file = String.fromCharCode(97 + this.props.files - x / this.props.squareSize + 1);
			let rank = 1 + Math.floor(y / this.props.squareSize);
			return file + rank;
		} else {
			let file = String.fromCharCode(97 + x / this.props.squareSize - 1);
			let rank = 1 + Math.floor((this.props.ranks * this.props.squareSize - y) / this.props.squareSize);
			return file + rank;
		}
	}

	// private actions

	_grab(x,y) {
		let boardW = this.props.squareSize * (1+this.props.files);
		let boardH = this.props.squareSize * (this.props.ranks);
		if(x < this.props.squareSize || x > boardW || y < 0 || y > boardH) {
			//outside the board ...
			return false;
		}
		let selectedSquare = this._coordsToSquare(x,y);
		let selectedPiece = this._getPieceAtSquare(selectedSquare);

		this.setState({
			selectedSquare: selectedSquare,
			selectedPieceType: selectedPiece ? selectedPiece.pieceType : null,
			dragX: selectedPiece ? selectedPiece.x + this.props.squareSize / 2: this.state.dragX,
			dragY: selectedPiece ? selectedPiece.y + this.props.squareSize / 2: this.state.dragY,
			isDragging: true
		});

		if(this.props.onSelectSquare) {
			this.props.onSelectSquare(selectedSquare);
		}
	}

	_move(x, y) {
		if(this.state.isDragging) {
			this.setState({dragX: x, dragY: y});
		}
	}

	_release(x,y) {
		this.setState({isDragging: false});
		let finalSquare = this._coordsToSquare(x,y);
		if(finalSquare !== this.state.selectedSquare) {
			if(this.props.onMovePiece) { // call the callback fn
				this.props.onMovePiece(this.state.selectedPieceType, this.state.selectedSquare, finalSquare);
			}
			this.setState({selectedSquare: null});
			return;
		}
	}

	// self-enquiry ////

	_getClientPos() {
		let rect = ReactDOM.findDOMNode(this).getBoundingClientRect();
		this.setState({left: rect.left, top: rect.top, width: rect.width, height: rect.height});
	}

	_getPieces() {
		if(!this.props.pieces)
			return [];

		return this.props.pieces.map((pieceString) => {
			let [pieceType, square ] = pieceString.split('@',2);	// split 'piece@square' into pieceType, square
			if(!square)
				return {pieceType: 'invalid', square: 'none', x: 0,y: 0}; // guard against nonsense input
			let [x,y] = this._squareToCoords(square);
			if (isNaN(y))
				return {pieceType: 'invalid', square: 'none', x: 0,y: 0}; // invalid y-coordinate
			return {pieceType: pieceType, square: square.toLowerCase(), x: x, y: y};
		});
	}

	_getPiecesFromFEN() {
		let pieces = [];
		let fields = this.props.fen.split(" ", 6);
		let rank=this.props.ranks-1, file = 0; // (zero-based)
		let x,y,square;
		const pieceDefinitions = Object.assign(standardPieceDefinitions, this.props.pieceDefinitions);
		const pieceChars = new RegExp('[' + Object.keys(pieceDefinitions).join('').replace('-', '\\-') + ']');
		for (let i = 0; i<fields[0].length; i++) {
			let c = fields[0].charAt(i);
			if(pieceChars.test(c)) {
				[x,y] = this._fileRankToCoords(file, rank);
				square = String.fromCharCode(97 + file) + (rank + 1).toString();
				pieces.push({pieceType: c, square: square, x: x, y: y});
				file++;
			} else if (c === "/") {
				rank -= 1;
				file = 0;
			}	else if(/[1-9]/.test(c)) {
				file += Number(c);
			}
		}
		return pieces;
	}

	_getPieceAtSquare(square) {
		let pieces = this.props.fen ? this._getPiecesFromFEN() : this._getPieces();
		return pieces.filter(pieceLocation => pieceLocation.square === square)[0];
	}

	// render function

	render() {
		let pieces = this.props.fen ? this._getPiecesFromFEN() : this._getPieces();
		const pieceDefinitions = Object.assign(standardPieceDefinitions, this.props.pieceDefinitions);
		return (
				<svg
					width={this.props.width === "auto" ? (1 + this.props.files) * this.props.squareSize : this.props.width}
					height={this.props.height === "auto" ? (1 + this.props.ranks) * this.props.squareSize : this.props.height}
					onMouseDown={this._onMouseDown.bind(this)}
					onTouchStart={this._onTouchStart.bind(this)}
					onMouseMove={this._onMouseMove.bind(this)}
					onTouchMove={this._onTouchMove.bind(this)}
					onMouseUp={this._onMouseUp.bind(this)}
					onTouchEnd={this._onTouchEnd.bind(this)}
				>

					<Board
						squareSize={this.props.squareSize} ranks={this.props.ranks} files={this.props.files} selectedSquare={this.state.selectedSquare}
						lightSquareColor={this.props.lightSquareColor} darkSquareColor={this.props.darkSquareColor} flip={!!this.props.flip}
					/>

					{pieces.map((piece, i) =>
						<Piece
							x={this.state.isDragging && piece.square === this.state.selectedSquare ? this.state.dragX - this.props.squareSize / 2 : piece.x}
							y={this.state.isDragging && piece.square === this.state.selectedSquare ? this.state.dragY - this.props.squareSize / 2 : piece.y}
							key={i} pieceType={piece.pieceType} squareSize={this.props.squareSize}
							drawPiece={pieceDefinitions[piece.pieceType]}
						/>
					)}

				</svg>
		);
	}
}

Chessdiagram.propTypes = {
	squareSize: React.PropTypes.number,
	ranks: React.PropTypes.number,
	files: React.PropTypes.number,
	lightSquareColor: React.PropTypes.string,
	darkSquareColor: React.PropTypes.string,
	/** if true, rotates the board so that Black pawns are moving up, and White pawns are moving down the board */
	flip: React.PropTypes.bool,
	/** callback function which is called when user moves a piece. Passes pieceType, initialSquare, finalSquare as parameters to callback */
	onMovePiece: React.PropTypes.func,
	/** callback function which is called when user clicks on a square. Passes name of square as parameter to callback */
	onSelectSquare: React.PropTypes.func,
	/** width of main svg container in pixels. If setting this manually, it should be at least 9 * squareSize to fit board AND labels*/
	width: React.PropTypes.oneOfType([
		React.PropTypes.string,
		React.PropTypes.number,
	]),
	/** height of main svg container in pixels. If setting this manually, it should be at least 9 * squareSize to fit board AND labels*/
	height: React.PropTypes.oneOfType([
		React.PropTypes.string,
		React.PropTypes.number,
	]),

	/** Chess position in FEN format (Forsyth-Edwards Notation). eg "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1" */
	fen: React.PropTypes.string,

	/** array of pieces at particular squares (alternative to fen) eg ['P@f2','P@g2','P@h2','K@g1']
	 * This format may be more suitable for unconventional board dimensions, for which standard FEN would not work
	 * Note: If both fen and pieces props are present, fen will take precedence */
	pieces: React.PropTypes.array,
	/** Optional associative array containing non-standard chess characters
	*/
	pieceDefinitions: React.PropTypes.object,
};

Chessdiagram.defaultProps = {
	width: 'auto',
	height: 'auto',
	squareSize: 45,
	ranks: 8,
	files: 8,
	lightSquareColor: "#2492FF",
	darkSquareColor:  "#005EBB",
	flip: false,
	pieceDefinitions: {},
};

export default Chessdiagram;
<|endoftext|>


<commit_before>var async = require('async');
var db = require('./db');
var moment = require('moment');
var selector = require('./selector');
module.exports = function getStatus(cb) {
    async.parallel({
        matches: function(cb) {
            db.matches.count({}, cb);
        },
        players: function(cb) {
            db.players.count({}, cb);
        },
        visited: function(cb) {
            db.players.count({
                last_visited: {
                    $ne: null
                }
            }, cb);
        },
        tracked_players: function(cb) {
            db.players.count(selector("tracked"), cb);
        },
        matches_last_day: function(cb) {
            db.matches.find({
                start_time: {
                    $gt: Number(moment().subtract(1, 'day').format('X'))
                }
            }, function(err, docs){
                var count = docs ? docs.length : 0;
                cb(err, count);
            });
        },
        queued_last_day: function(cb) {
            db.matches.find({
                start_time: {
                    $gt: Number(moment().subtract(1, 'day').format('X'))
                }
            }, {
                fields: {
                    "parse_status": 1
                }
            }, function(err, docs) {
                var count = docs ? docs.filter(function(m) {
                    return m.parse_status === 0;
                }).length : 0;
                cb(err, count);
            });
        },
        skipped_last_day: function(cb) {
            db.matches.find({
                start_time: {
                    $gt: Number(moment().subtract(1, 'day').format('X'))
                }
            }, {
                fields: {
                    "parse_status": 1
                }
            }, function(err, docs) {
                var count = docs ? docs.filter(function(m) {
                    return m.parse_status === 3;
                }).length : 0;
                cb(err, count);
            });
        },
        parsed_last_day: function(cb) {
            db.matches.find({
                start_time: {
                    $gt: Number(moment().subtract(1, 'day').format('X'))
                }
            }, {
                fields: {
                    "parse_status": 1
                }
            }, function(err, docs) {
                var count = docs ? docs.filter(function(m) {
                    return m.parse_status === 2;
                }).length : 0;
                cb(err, count);
            });
        },
        unavailable_last_day: function(cb) {
            db.matches.find({
                start_time: {
                    $gt: Number(moment().subtract(1, 'day').format('X'))
                },
            }, {
                fields: {
                    "parse_status": 1
                }
            }, function(err, docs) {
                var count = docs ? docs.filter(function(m) {
                    return m.parse_status === 1;
                }).length : 0;
                cb(err, count);
            });
        },
        full_history: function(cb) {
            db.players.count({
                full_history_time: {
                    $ne: null
                }
            }, cb);
        },
        full_history_eligible: function(cb) {
            var base = selector("tracked");
            base.full_history_time = null;
            db.players.count(base, cb);
        },
        last_added: function(cb) {
            db.matches.find({}, {
                sort: {
                    match_seq_num: -1
                },
                fields: {
                    match_id: 1,
                    start_time: 1,
                    duration: 1
                },
                limit: 10
            }, cb);
        },
        last_parsed: function(cb) {
            db.matches.find({
                parse_status: 2
            }, {
                sort: {
                    match_seq_num: -1
                },
                fields: {
                    match_id: 1,
                    start_time: 1,
                    duration: 1
                },
                limit: 10
            }, cb);
        }
    }, cb);
};<commit_msg>removed parallel<commit_after>var async = require('async');
var db = require('./db');
var moment = require('moment');
var selector = require('./selector');
module.exports = function getStatus(cb) {
    async.series({
        matches: function(cb) {
            db.matches.count({}, cb);
        },
        players: function(cb) {
            db.players.count({}, cb);
        },
        visited: function(cb) {
            db.players.count({
                last_visited: {
                    $ne: null
                }
            }, cb);
        },
        tracked_players: function(cb) {
            db.players.count(selector("tracked"), cb);
        },
        matches_last_day: function(cb) {
            db.matches.find({
                start_time: {
                    $gt: Number(moment().subtract(1, 'day').format('X'))
                }
            }, function(err, docs){
                var count = docs ? docs.length : 0;
                cb(err, count);
            });
        },
        queued_last_day: function(cb) {
            db.matches.find({
                start_time: {
                    $gt: Number(moment().subtract(1, 'day').format('X'))
                }
            }, {
                fields: {
                    "parse_status": 1
                }
            }, function(err, docs) {
                var count = docs ? docs.filter(function(m) {
                    return m.parse_status === 0;
                }).length : 0;
                cb(err, count);
            });
        },
        skipped_last_day: function(cb) {
            db.matches.find({
                start_time: {
                    $gt: Number(moment().subtract(1, 'day').format('X'))
                }
            }, {
                fields: {
                    "parse_status": 1
                }
            }, function(err, docs) {
                var count = docs ? docs.filter(function(m) {
                    return m.parse_status === 3;
                }).length : 0;
                cb(err, count);
            });
        },
        parsed_last_day: function(cb) {
            db.matches.find({
                start_time: {
                    $gt: Number(moment().subtract(1, 'day').format('X'))
                }
            }, {
                fields: {
                    "parse_status": 1
                }
            }, function(err, docs) {
                var count = docs ? docs.filter(function(m) {
                    return m.parse_status === 2;
                }).length : 0;
                cb(err, count);
            });
        },
        unavailable_last_day: function(cb) {
            db.matches.find({
                start_time: {
                    $gt: Number(moment().subtract(1, 'day').format('X'))
                },
            }, {
                fields: {
                    "parse_status": 1
                }
            }, function(err, docs) {
                var count = docs ? docs.filter(function(m) {
                    return m.parse_status === 1;
                }).length : 0;
                cb(err, count);
            });
        },
        full_history: function(cb) {
            db.players.count({
                full_history_time: {
                    $ne: null
                }
            }, cb);
        },
        full_history_eligible: function(cb) {
            var base = selector("tracked");
            base.full_history_time = null;
            db.players.count(base, cb);
        },
        last_added: function(cb) {
            db.matches.find({}, {
                sort: {
                    match_seq_num: -1
                },
                fields: {
                    match_id: 1,
                    start_time: 1,
                    duration: 1
                },
                limit: 10
            }, cb);
        },
        last_parsed: function(cb) {
            db.matches.find({
                parse_status: 2
            }, {
                sort: {
                    match_seq_num: -1
                },
                fields: {
                    match_id: 1,
                    start_time: 1,
                    duration: 1
                },
                limit: 10
            }, cb);
        }
    }, cb);
};<|endoftext|>