<commit_before>/**
 * "Lorem ipsum" text generator. Matches lipsum(num)? or
 * lorem(num)? abbreviation.
 * This code is based on Django's contribution:
 * https://code.djangoproject.com/browser/django/trunk/django/contrib/webdesign/lorem_ipsum.py
 *

 * Examples to test:

 * lipsum – generates 30 words text.

 * lipsum*6 – generates 6 paragraphs (autowrapped with <p> element) of text.

 * ol>lipsum10*5 — generates ordered list with 5 list items (autowrapped with <li> tag)
 * with text of 10 words on each line

 * span*3>lipsum20 – generates 3 paragraphs of 20-words text, each wrapped with <span> element .
 * Each paragraph phrase is unique
 * @param {Function} require
 * @param {Underscore} _
 * @constructor
 * @memberOf __loremIpsumGeneratorDefine
 */
emmet.define('lorem', function(require, _) {
	var langs = {
		en: {
			common: ['lorem', 'ipsum', 'dolor', 'sit', 'amet', 'consectetur', 'adipisicing', 'elit'],
			words: ['exercitationem', 'perferendis', 'perspiciatis', 'laborum', 'eveniet',
	             'sunt', 'iure', 'nam', 'nobis', 'eum', 'cum', 'officiis', 'excepturi',
	             'odio', 'consectetur', 'quasi', 'aut', 'quisquam', 'vel', 'eligendi',
	             'itaque', 'non', 'odit', 'tempore', 'quaerat', 'dignissimos',
	             'facilis', 'neque', 'nihil', 'expedita', 'vitae', 'vero', 'ipsum',
	             'nisi', 'animi', 'cumque', 'pariatur', 'velit', 'modi', 'natus',
	             'iusto', 'eaque', 'sequi', 'illo', 'sed', 'ex', 'et', 'voluptatibus',
	             'tempora', 'veritatis', 'ratione', 'assumenda', 'incidunt', 'nostrum',
	             'placeat', 'aliquid', 'fuga', 'provident', 'praesentium', 'rem',
	             'necessitatibus', 'suscipit', 'adipisci', 'quidem', 'possimus',
	             'voluptas', 'debitis', 'sint', 'accusantium', 'unde', 'sapiente',
	             'voluptate', 'qui', 'aspernatur', 'laudantium', 'soluta', 'amet',
	             'quo', 'aliquam', 'saepe', 'culpa', 'libero', 'ipsa', 'dicta',
	             'reiciendis', 'nesciunt', 'doloribus', 'autem', 'impedit', 'minima',
	             'maiores', 'repudiandae', 'ipsam', 'obcaecati', 'ullam', 'enim',
	             'totam', 'delectus', 'ducimus', 'quis', 'voluptates', 'dolores',
	             'molestiae', 'harum', 'dolorem', 'quia', 'voluptatem', 'molestias',
	             'magni', 'distinctio', 'omnis', 'illum', 'dolorum', 'voluptatum', 'ea',
	             'quas', 'quam', 'corporis', 'quae', 'blanditiis', 'atque', 'deserunt',
	             'laboriosam', 'earum', 'consequuntur', 'hic', 'cupiditate',
	             'quibusdam', 'accusamus', 'ut', 'rerum', 'error', 'minus', 'eius',
	             'ab', 'ad', 'nemo', 'fugit', 'officia', 'at', 'in', 'id', 'quos',
	             'reprehenderit', 'numquam', 'iste', 'fugiat', 'sit', 'inventore',
	             'beatae', 'repellendus', 'magnam', 'recusandae', 'quod', 'explicabo',
	             'doloremque', 'aperiam', 'consequatur', 'asperiores', 'commodi',
	             'optio', 'dolor', 'labore', 'temporibus', 'repellat', 'veniam',
	             'architecto', 'est', 'esse', 'mollitia', 'nulla', 'a', 'similique',
	             'eos', 'alias', 'dolore', 'tenetur', 'deleniti', 'porro', 'facere',
	             'maxime', 'corrupti']
		},
		ru: {
			common: ['далеко-далеко', 'за', 'словесными', 'горами', 'в стране', 'гласных', 'и согласных', 'живут', 'рыбные', 'тексты'],
			words: ['вдали', 'от всех', 'они', 'буквенных', 'домах', 'на берегу', 'семантика',
		            'большого', 'языкового', 'океана', 'маленький', 'ручеек', 'даль',
		            'журчит', 'по всей', 'обеспечивает', 'ее','всеми', 'необходимыми',
		            'правилами', 'эта', 'парадигматическая', 'страна', 'которой', 'жаренные',
		            'предложения', 'залетают', 'прямо', 'рот', 'даже', 'всемогущая',
		            'пунктуация', 'не', 'имеет', 'власти', 'над', 'рыбными', 'текстами',
		            'ведущими', 'безорфографичный', 'образ', 'жизни', 'однажды', 'одна',
		            'маленькая', 'строчка','рыбного', 'текста', 'имени', 'lorem', 'ipsum',
		            'решила', 'выйти', 'большой', 'мир', 'грамматики', 'великий', 'оксмокс',
		            'предупреждал', 'о', 'злых', 'запятых', 'диких', 'знаках', 'вопроса',
		            'коварных', 'точках', 'запятой', 'но', 'текст', 'дал', 'сбить',
		            'себя', 'толку', 'он', 'собрал', 'семь', 'своих', 'заглавных', 'букв',
		            'подпоясал', 'инициал', 'за', 'пояс', 'пустился', 'дорогу',
		            'взобравшись', 'первую', 'вершину', 'курсивных', 'гор', 'бросил',
		            'последний', 'взгляд', 'назад', 'силуэт', 'своего', 'родного', 'города',
		            'буквоград', 'заголовок', 'деревни', 'алфавит', 'подзаголовок', 'своего',
		            'переулка', 'грустный', 'реторический', 'вопрос', 'скатился', 'его',
		            'щеке', 'продолжил', 'свой', 'путь', 'дороге', 'встретил', 'рукопись',
		            'она', 'предупредила',  'моей', 'все', 'переписывается', 'несколько',
		            'раз', 'единственное', 'что', 'меня', 'осталось', 'это', 'приставка',
		            'возвращайся', 'ты', 'лучше', 'свою', 'безопасную', 'страну', 'послушавшись',
		            'рукописи', 'наш', 'продолжил', 'свой', 'путь', 'вскоре', 'ему',
		            'повстречался', 'коварный', 'составитель', 'рекламных', 'текстов',
		            'напоивший', 'языком', 'речью', 'заманивший', 'свое', 'агенство',
		            'которое', 'использовало', 'снова', 'снова', 'своих', 'проектах',
		            'если', 'переписали', 'то', 'живет', 'там', 'до', 'сих', 'пор']
		}
	};

	var prefs = require('preferences');
	prefs.define('lorem.defaultLang', 'en');

	/**
	 * @param {AbbreviationNode} tree
	 * @param {Object} options
	 */
	require('abbreviationParser').addPreprocessor(function(tree, options) {
		var re = /^(?:lorem|lipsum)([a-z]{2})?(\d*)$/i, match;

		/** @param {AbbreviationNode} node */
		tree.findAll(function(node) {
			if (node._name && (match = node._name.match(re))) {
				var wordCound = match[2] || 30;
				var lang = match[1] || prefs.get('lorem.defaultLang') || 'en';

				// force node name resolving if node should be repeated
				// or contains attributes. In this case, node should be outputed
				// as tag, otherwise as text-only node
				node._name = '';
				node.data('forceNameResolving', node.isRepeating() || node.attributeList().length);
				node.data('pasteOverwrites', true);
				node.data('paste', function(i, content) {
					return paragraph(lang, wordCound, !i);
				});
			}
		});
	});

	/**
	 * Returns random integer between from and to values
	 * @param {Number} from
	 * @param {Number} to
	 * @returns {Number}
	 */
	function randint(from, to) {
		return Math.round(Math.random() * (to - from) + from);
	}

	/**
	 * @param {Array} arr
	 * @param {Number} count
	 * @returns {Array}
	 */
	function sample(arr, count) {
		var len = arr.length;
		var iterations = Math.min(len, count);
		var result = [];
		while (result.length < iterations) {
			var randIx = randint(0, len - 1);
			if (!_.include(result, randIx))
				result.push(randIx);
		}

		return _.map(result, function(ix) {
			return arr[ix];
		});
	}

	function choice(val) {
		if (_.isString(val))
			return val.charAt(randint(0, val.length - 1));

		return val[randint(0, val.length - 1)];
	}

	function sentence(words, end) {
		if (words.length) {
			words[0] = words[0].charAt(0).toUpperCase() + words[0].substring(1);
		}

		return words.join(' ') + (end || choice('?!...')); // more dots that question marks
	}

	/**
	 * Insert commas at randomly selected words. This function modifies values
	 * inside words array
	 * @param {Array} words
	 */
	function insertCommas(words) {
		var len = words.length;
		var totalCommas = 0;

		if (len > 3 && len <= 6) {
			totalCommas = randint(0, 1);
		} else if (len > 6 && len <= 12) {
			totalCommas = randint(0, 2);
		} else {
			totalCommas = randint(1, 4);
		}

		_.each(_.range(totalCommas), function(ix) {
			words[ix] += ',';
		});
	}

	/**
	 * Generate a paragraph of "Lorem ipsum" text
	 * @param {Number} wordCount Words count in paragraph
	 * @param {Boolean} startWithCommon Should paragraph start with common
	 * "lorem ipsum" sentence.
	 * @returns {String}
	 */
	function paragraph(lang, wordCount, startWithCommon) {
		var data = langs[lang];
		if (!data) {
			return '';
		}

		var result = [];
		var totalWords = 0;
		var words;

		wordCount = parseInt(wordCount, 10);

		if (startWithCommon && data.common) {
			words = data.common.slice(0, wordCount);
			if (words.length > 5)
				words[4] += ',';
			totalWords += words.length;
			result.push(sentence(words, '.'));
		}

		while (totalWords < wordCount) {
			words = sample(data.words, Math.min(randint(3, 12) * randint(1, 5), wordCount - totalWords));
			totalWords += words.length;
			insertCommas(words);
			result.push(sentence(words));
		}

		return result.join(' ');
	}

	return {
		/**
		 * Adds new language words for Lorem Ipsum generator
		 * @param {String} lang Two-letter lang definition
		 * @param {Object} data Words for language. Maight be either a space-separated
		 * list of words (String), Array of words or object with text and
		 * common properties
		 */
		addLang: function(lang, data) {
			if (_.isString(data)) {
				data = {words: _.compact(data.split(' '))};
			} else if (_.isArray(data)) {
				data = {words: data};
			}

			langs[lang] = data;
		}
	}
});<commit_msg>Fixed few errors in comma insertion in Lorem Ipsum module<commit_after>/**
 * "Lorem ipsum" text generator. Matches lipsum(num)? or
 * lorem(num)? abbreviation.
 * This code is based on Django's contribution:
 * https://code.djangoproject.com/browser/django/trunk/django/contrib/webdesign/lorem_ipsum.py
 *

 * Examples to test:

 * lipsum – generates 30 words text.

 * lipsum*6 – generates 6 paragraphs (autowrapped with <p> element) of text.

 * ol>lipsum10*5 — generates ordered list with 5 list items (autowrapped with <li> tag)
 * with text of 10 words on each line

 * span*3>lipsum20 – generates 3 paragraphs of 20-words text, each wrapped with <span> element .
 * Each paragraph phrase is unique
 * @param {Function} require
 * @param {Underscore} _
 * @constructor
 * @memberOf __loremIpsumGeneratorDefine
 */
emmet.define('lorem', function(require, _) {
	var langs = {
		en: {
			common: ['lorem', 'ipsum', 'dolor', 'sit', 'amet', 'consectetur', 'adipisicing', 'elit'],
			words: ['exercitationem', 'perferendis', 'perspiciatis', 'laborum', 'eveniet',
	             'sunt', 'iure', 'nam', 'nobis', 'eum', 'cum', 'officiis', 'excepturi',
	             'odio', 'consectetur', 'quasi', 'aut', 'quisquam', 'vel', 'eligendi',
	             'itaque', 'non', 'odit', 'tempore', 'quaerat', 'dignissimos',
	             'facilis', 'neque', 'nihil', 'expedita', 'vitae', 'vero', 'ipsum',
	             'nisi', 'animi', 'cumque', 'pariatur', 'velit', 'modi', 'natus',
	             'iusto', 'eaque', 'sequi', 'illo', 'sed', 'ex', 'et', 'voluptatibus',
	             'tempora', 'veritatis', 'ratione', 'assumenda', 'incidunt', 'nostrum',
	             'placeat', 'aliquid', 'fuga', 'provident', 'praesentium', 'rem',
	             'necessitatibus', 'suscipit', 'adipisci', 'quidem', 'possimus',
	             'voluptas', 'debitis', 'sint', 'accusantium', 'unde', 'sapiente',
	             'voluptate', 'qui', 'aspernatur', 'laudantium', 'soluta', 'amet',
	             'quo', 'aliquam', 'saepe', 'culpa', 'libero', 'ipsa', 'dicta',
	             'reiciendis', 'nesciunt', 'doloribus', 'autem', 'impedit', 'minima',
	             'maiores', 'repudiandae', 'ipsam', 'obcaecati', 'ullam', 'enim',
	             'totam', 'delectus', 'ducimus', 'quis', 'voluptates', 'dolores',
	             'molestiae', 'harum', 'dolorem', 'quia', 'voluptatem', 'molestias',
	             'magni', 'distinctio', 'omnis', 'illum', 'dolorum', 'voluptatum', 'ea',
	             'quas', 'quam', 'corporis', 'quae', 'blanditiis', 'atque', 'deserunt',
	             'laboriosam', 'earum', 'consequuntur', 'hic', 'cupiditate',
	             'quibusdam', 'accusamus', 'ut', 'rerum', 'error', 'minus', 'eius',
	             'ab', 'ad', 'nemo', 'fugit', 'officia', 'at', 'in', 'id', 'quos',
	             'reprehenderit', 'numquam', 'iste', 'fugiat', 'sit', 'inventore',
	             'beatae', 'repellendus', 'magnam', 'recusandae', 'quod', 'explicabo',
	             'doloremque', 'aperiam', 'consequatur', 'asperiores', 'commodi',
	             'optio', 'dolor', 'labore', 'temporibus', 'repellat', 'veniam',
	             'architecto', 'est', 'esse', 'mollitia', 'nulla', 'a', 'similique',
	             'eos', 'alias', 'dolore', 'tenetur', 'deleniti', 'porro', 'facere',
	             'maxime', 'corrupti']
		},
		ru: {
			common: ['далеко-далеко', 'за', 'словесными', 'горами', 'в стране', 'гласных', 'и согласных', 'живут', 'рыбные', 'тексты'],
			words: ['вдали', 'от всех', 'они', 'буквенных', 'домах', 'на берегу', 'семантика',
		            'большого', 'языкового', 'океана', 'маленький', 'ручеек', 'даль',
		            'журчит', 'по всей', 'обеспечивает', 'ее','всеми', 'необходимыми',
		            'правилами', 'эта', 'парадигматическая', 'страна', 'которой', 'жаренные',
		            'предложения', 'залетают', 'прямо', 'рот', 'даже', 'всемогущая',
		            'пунктуация', 'не', 'имеет', 'власти', 'над', 'рыбными', 'текстами',
		            'ведущими', 'безорфографичный', 'образ', 'жизни', 'однажды', 'одна',
		            'маленькая', 'строчка','рыбного', 'текста', 'имени', 'lorem', 'ipsum',
		            'решила', 'выйти', 'большой', 'мир', 'грамматики', 'великий', 'оксмокс',
		            'предупреждал', 'о', 'злых', 'запятых', 'диких', 'знаках', 'вопроса',
		            'коварных', 'точках', 'запятой', 'но', 'текст', 'дал', 'сбить',
		            'себя', 'толку', 'он', 'собрал', 'семь', 'своих', 'заглавных', 'букв',
		            'подпоясал', 'инициал', 'за', 'пояс', 'пустился', 'дорогу',
		            'взобравшись', 'первую', 'вершину', 'курсивных', 'гор', 'бросил',
		            'последний', 'взгляд', 'назад', 'силуэт', 'своего', 'родного', 'города',
		            'буквоград', 'заголовок', 'деревни', 'алфавит', 'подзаголовок', 'своего',
		            'переулка', 'грустный', 'реторический', 'вопрос', 'скатился', 'его',
		            'щеке', 'продолжил', 'свой', 'путь', 'дороге', 'встретил', 'рукопись',
		            'она', 'предупредила',  'моей', 'все', 'переписывается', 'несколько',
		            'раз', 'единственное', 'что', 'меня', 'осталось', 'это', 'приставка',
		            'возвращайся', 'ты', 'лучше', 'свою', 'безопасную', 'страну', 'послушавшись',
		            'рукописи', 'наш', 'продолжил', 'свой', 'путь', 'вскоре', 'ему',
		            'повстречался', 'коварный', 'составитель', 'рекламных', 'текстов',
		            'напоивший', 'языком', 'речью', 'заманивший', 'свое', 'агенство',
		            'которое', 'использовало', 'снова', 'снова', 'своих', 'проектах',
		            'если', 'переписали', 'то', 'живет', 'там', 'до', 'сих', 'пор']
		}
	};

	var prefs = require('preferences');
	prefs.define('lorem.defaultLang', 'en');

	/**
	 * @param {AbbreviationNode} tree
	 * @param {Object} options
	 */
	require('abbreviationParser').addPreprocessor(function(tree, options) {
		var re = /^(?:lorem|lipsum)([a-z]{2})?(\d*)$/i, match;

		/** @param {AbbreviationNode} node */
		tree.findAll(function(node) {
			if (node._name && (match = node._name.match(re))) {
				var wordCound = match[2] || 30;
				var lang = match[1] || prefs.get('lorem.defaultLang') || 'en';

				// force node name resolving if node should be repeated
				// or contains attributes. In this case, node should be outputed
				// as tag, otherwise as text-only node
				node._name = '';
				node.data('forceNameResolving', node.isRepeating() || node.attributeList().length);
				node.data('pasteOverwrites', true);
				node.data('paste', function(i, content) {
					return paragraph(lang, wordCound, !i);
				});
			}
		});
	});

	/**
	 * Returns random integer between from and to values
	 * @param {Number} from
	 * @param {Number} to
	 * @returns {Number}
	 */
	function randint(from, to) {
		return Math.round(Math.random() * (to - from) + from);
	}

	/**
	 * @param {Array} arr
	 * @param {Number} count
	 * @returns {Array}
	 */
	function sample(arr, count) {
		var len = arr.length;
		var iterations = Math.min(len, count);
		var result = [];
		while (result.length < iterations) {
			var randIx = randint(0, len - 1);
			if (!_.include(result, randIx))
				result.push(randIx);
		}

		return _.map(result, function(ix) {
			return arr[ix];
		});
	}

	function choice(val) {
		if (_.isString(val))
			return val.charAt(randint(0, val.length - 1));

		return val[randint(0, val.length - 1)];
	}

	function sentence(words, end) {
		if (words.length) {
			words[0] = words[0].charAt(0).toUpperCase() + words[0].substring(1);
		}

		return words.join(' ') + (end || choice('?!...')); // more dots that question marks
	}

	/**
	 * Insert commas at randomly selected words. This function modifies values
	 * inside words array
	 * @param {Array} words
	 */
	function insertCommas(words) {
		var len = words.length;
		var totalCommas = 0;

		if (len > 3 && len <= 6) {
			totalCommas = randint(0, 1);
		} else if (len > 6 && len <= 12) {
			totalCommas = randint(0, 2);
		} else {
			totalCommas = randint(1, 4);
		}

		_.each(_.range(totalCommas), function(ix) {
			if (ix < words.length - 1) {
				words[ix] += ',';
			}
		});
	}

	/**
	 * Generate a paragraph of "Lorem ipsum" text
	 * @param {Number} wordCount Words count in paragraph
	 * @param {Boolean} startWithCommon Should paragraph start with common
	 * "lorem ipsum" sentence.
	 * @returns {String}
	 */
	function paragraph(lang, wordCount, startWithCommon) {
		var data = langs[lang];
		if (!data) {
			return '';
		}

		var result = [];
		var totalWords = 0;
		var words;

		wordCount = parseInt(wordCount, 10);

		if (startWithCommon && data.common) {
			words = data.common.slice(0, wordCount);
			if (words.length > 5)
				words[4] += ',';
			totalWords += words.length;
			result.push(sentence(words, '.'));
		}

		while (totalWords < wordCount) {
			words = sample(data.words, Math.min(randint(3, 12) * randint(1, 5), wordCount - totalWords));
			totalWords += words.length;
			insertCommas(words);
			result.push(sentence(words));
		}

		return result.join(' ');
	}

	return {
		/**
		 * Adds new language words for Lorem Ipsum generator
		 * @param {String} lang Two-letter lang definition
		 * @param {Object} data Words for language. Maight be either a space-separated
		 * list of words (String), Array of words or object with text and
		 * common properties
		 */
		addLang: function(lang, data) {
			if (_.isString(data)) {
				data = {words: _.compact(data.split(' '))};
			} else if (_.isArray(data)) {
				data = {words: data};
			}

			langs[lang] = data;
		}
	}
});<|endoftext|>


<commit_before>var fetch = require("node-fetch")
var helpers = require("../helpers")

// Use cinemeta to pull names of movies and series against IMDB IDs
var cinemetaUrls = {
    'movie': 'https://cinemeta.strem.io/stremioget/stremio/v1/q.json?b=eyJwYXJhbXMiOltudWxsLHt9XSwibWV0aG9kIjoibmFtZXMubW92aWUiLCJpZCI6MSwianNvbnJwYyI6IjIuMCJ9',
    'series': 'https://cinemeta.strem.io/stremioget/stremio/v1/q.json?b=eyJwYXJhbXMiOltudWxsLHt9XSwibWV0aG9kIjoibmFtZXMuc2VyaWVzIiwiaWQiOjEsImpzb25ycGMiOiIyLjAifQ==',
}

// Index entry in our in-mem index
function indexEntry(entry) {
    if (entry.year) entry.year = parseInt(entry.year.toString().split("-")[0]); // first year for series
    var n = helpers.simplifyName(entry);
    if (!meta[n]) meta[n] = [];
    meta[n].push(entry);
    byImdb[entry.imdb_id] = entry;
}

// Find in our metadata set
var pulled = { movie: false, series: false };
var meta = { }, byImdb = { };

function metadataFind(query, cb) {
    // It's OK if we don't pass type and we don't fetch names, because we will go to google fallback
    if (query.type && !pulled[query.type] && cinemetaUrls[query.type]) {
        fetch(cinemetaUrls[query.type])
        .then(function(resp) { return resp.json() })
        .then(function(resp) { return resp.result })
        .then(function(res) {
            res.forEach(indexEntry);
            pulled[query.type] = 1;
        })
        .catch(function(e) {
            console.error(e)
        })
        .then(function() {
            match()
        })
    } else process.nextTick(match);

    function match() {
        var name = helpers.simplifyName(query)
        if (!name) return cb(null, null)
        var matches = meta[name] || [ ];
        var m = matches.find(function(match) {
            if (!match.type === query.type) return false

            if (query.type === 'movie' && query.hasOwnProperty('year'))
                return helpers.yearSimilar(query.year, match.year)

            return true
        })
        return cb(null, m && m.imdb_id);
    };
}

module.exports = metadataFind
<commit_msg>Fix Metadata Matching<commit_after>var fetch = require("node-fetch")
var helpers = require("../helpers")

// Use cinemeta to pull names of movies and series against IMDB IDs
var cinemetaUrls = {
    'movie': 'https://cinemeta.strem.io/stremioget/stremio/v1/q.json?b=eyJwYXJhbXMiOltudWxsLHt9XSwibWV0aG9kIjoibmFtZXMubW92aWUiLCJpZCI6MSwianNvbnJwYyI6IjIuMCJ9',
    'series': 'https://cinemeta.strem.io/stremioget/stremio/v1/q.json?b=eyJwYXJhbXMiOltudWxsLHt9XSwibWV0aG9kIjoibmFtZXMuc2VyaWVzIiwiaWQiOjEsImpzb25ycGMiOiIyLjAifQ==',
}

// Index entry in our in-mem index
function indexEntry(entry) {
    if (entry.year) entry.year = parseInt(entry.year.toString().split("-")[0]); // first year for series
    var n = helpers.simplifyName(entry);
    if (!meta[n]) meta[n] = [];
    meta[n].push(entry);
    byImdb[entry.imdb_id] = entry;
}

// Find in our metadata set
var pulled = { movie: false, series: false };
var meta = { }, byImdb = { };

function metadataFind(query, cb) {
    // It's OK if we don't pass type and we don't fetch names, because we will go to google fallback
    if (query.type && !pulled[query.type] && cinemetaUrls[query.type]) {
        fetch(cinemetaUrls[query.type])
        .then(function(resp) { return resp.json() })
        .then(function(resp) { return resp.result })
        .then(function(res) {
            res.forEach(indexEntry);
            pulled[query.type] = 1;
        })
        .catch(function(e) {
            console.error(e)
        })
        .then(function() {
            match()
        })
    } else process.nextTick(match);

    function match() {
        var name = helpers.simplifyName(query)
        if (!name) return cb(null, null)
        var matches = meta[name] || [ ];
        var m = matches.find(function(match) {
            if (!(match.type === query.type)) return false

            if (query.type === 'movie' && query.hasOwnProperty('year'))
                return helpers.yearSimilar(query.year, match.year)

            return true
        })
        return cb(null, m && m.imdb_id);
    };
}

module.exports = metadataFind
<|endoftext|>


<commit_before>'use strict';
/**
 * @fileOverview This is a grunt task to precompile JST files with the option to
 *               expose the result into module.exports rather than a namespace.
 *               This has been forked and modified from grunt-contrib-jst and
 *               differs slightly. It retains all of the options of the
 *               original, but adds a new one called module. This
 *               is like the amdWrapper option, except it will create
 *               exports[filename] = templateCode() instead so that if you use
 *               browserify to package your code, or if you just want to call it
 *               from the server. And this one uses lodash. So there.
 *
 * @module tasks\grunt-jst-module
 * @see http://gruntjs.com/
 * @see https://github.com/gruntjs/grunt-contrib-jst
 * @copyright Copyright © 2012 Terry Weiss, Tim Branyen, grunt-contrib contributers. All rights reserved.
 * @license MIT.
 */

/**
 * Figures out what the full namespace declaration looks like when rendered.
 *
 * @param {string} ns The namespace specification
 * @return {Object} And object with two components: namespace - the namespace specification and
 * declaration: the component declarations to make sure the namespace is valid at runtime.
 */
var getNamespaceDeclaration = function ( ns ) {
	var output = [];
	var curPath = 'this';
	if ( ns !== 'this' ) {
		var nsParts = ns.split( '.' );
		nsParts.forEach( function ( curPart ) {
			if ( curPart !== 'this' ) {
				curPath += '[' + JSON.stringify( curPart ) + ']';
				output.push( curPath + ' = ' + curPath + ' || {};' );
			}
		} );
	}

	return {
		namespace   : curPath,
		declaration : output.join( '\n' )
	};
};
/**
 * The task itself
 * @param {Grunt} grunt The grunt object
 */
module.exports = function ( grunt ) {

	var path = require( "path" );

	grunt.registerMultiTask( 'template-module', 'Compile underscore templates to JST file that can be exposed as a module', function () {
		var sys = require( "lodash" );
		var beautifier = require( "node-beautify" );

		var defaultOptions = {
			namespace        : null,
			templateSettings : {
				client       : true,
				compileDebug : true
			},
			lintExpr         : {
				//				unused : false, asi : true, expr : true
			},
			module           : true,
			requireProvider  : true,
			provider         : "underscore",
			processName      : function ( name ) {
				return name;
			},
			useStrict        : false,
			single 			 : false,
			prettify         : false,
			prettifyOptions  : {
				indentSize : 2
			}
		};

		var options = sys.extend( {}, defaultOptions, this.options() );
		var templateProvider = require( options.provider );

		grunt.verbose.writeflags( options, 'Options' );

		var nsInfo;
		// we want to turn module off in the event other setting would collide with it
		if ( options.amdWrapper || !sys.isEmpty( options.namespace ) ) {
			options.module = false;
		}
		if ( options.module ) {
			options.amdWrapper = false;
			nsInfo = {
				namespace   : "exports",
				declaration : ""
			};
		} else {
			options.module = false;
			options.requireProvider = false;
			options.namespace = options.namespace || "JST";
			nsInfo = getNamespaceDeclaration( options.namespace );
		}

		var output = [];
		var compiled, templateName;
		var oneSource = (this.files.length === 1);

		this.files.forEach( function ( f ) {

			sys.each( f.src, function ( srcFile ) {
				var fpath;
				if ( f.cwd ) {
					fpath = path.resolve( f.cwd, srcFile );
				} else {
					fpath = srcFile;
				}
				var src = grunt.file.read( fpath );
				try {
					if ( options.provider === "ejs" ) {
						compiled = templateProvider.compile( src, options.templateSettings );
					} else {
						compiled = templateProvider.template( src, false, options.templateSettings ).source;
					}

					if ( options.single === true && options.module === true && oneSource )
					{
						output.push( "module.exports = " + compiled + ";" );
					}
					else
					{
						templateName = options.processName( srcFile );
						output.push( nsInfo.namespace + "[" + JSON.stringify( templateName ) + "] = " + compiled + ";" );
					}
				} catch ( e ) {
					grunt.log.error( e );
					grunt.fail.warn( "file failed to compile." );
				}
			} );

			if ( output.length > 0 ) {
				if ( !sys.isEmpty( nsInfo.declaration ) ) {
					output.unshift( nsInfo.declaration );
				}
				if ( options.amdWrapper ) {
					var amdDefine = typeof options.amdWrapper === "string" ? options.amdWrapper : "define(function(){";
					output.unshift( amdDefine );
					output.push( "  return " + nsInfo.namespace + ";\n});" );
				} else if ( options.requireProvider ) {
					output.unshift( ["var _ = require('" + options.provider + "');"] );
				}
				if ( options.lintExpr && !sys.isEmpty( options.lintExpr ) ) {
					var lintlines = sys.map( options.lintExpr, function ( v, k ) {
						return k + ", " + v;
					} );
					output.push( "\n jshint " + lintlines.join( " " ) );
				}

				if ( options.useStrict ) {
					output.unshift( '"use strict;"\n' );
				}

				var contents = output.join( "\n" );
				if ( options.prettify ) {
					contents = beautifier.beautifyJs( contents, options.prettifyOptions );
				}

				grunt.file.write( f.dest, contents );
				grunt.log.writeln( "File '" + f.dest + "' created." );

			}
		} );

	} );
};
<commit_msg>Add support for filename and template includes for ejs<commit_after>'use strict';
/**
 * @fileOverview This is a grunt task to precompile JST files with the option to
 *               expose the result into module.exports rather than a namespace.
 *               This has been forked and modified from grunt-contrib-jst and
 *               differs slightly. It retains all of the options of the
 *               original, but adds a new one called module. This
 *               is like the amdWrapper option, except it will create
 *               exports[filename] = templateCode() instead so that if you use
 *               browserify to package your code, or if you just want to call it
 *               from the server. And this one uses lodash. So there.
 *
 * @module tasks\grunt-jst-module
 * @see http://gruntjs.com/
 * @see https://github.com/gruntjs/grunt-contrib-jst
 * @copyright Copyright © 2012 Terry Weiss, Tim Branyen, grunt-contrib contributers. All rights reserved.
 * @license MIT.
 */

/**
 * Figures out what the full namespace declaration looks like when rendered.
 *
 * @param {string} ns The namespace specification
 * @return {Object} And object with two components: namespace - the namespace specification and
 * declaration: the component declarations to make sure the namespace is valid at runtime.
 */
var getNamespaceDeclaration = function ( ns ) {
	var output = [];
	var curPath = 'this';
	if ( ns !== 'this' ) {
		var nsParts = ns.split( '.' );
		nsParts.forEach( function ( curPart ) {
			if ( curPart !== 'this' ) {
				curPath += '[' + JSON.stringify( curPart ) + ']';
				output.push( curPath + ' = ' + curPath + ' || {};' );
			}
		} );
	}

	return {
		namespace   : curPath,
		declaration : output.join( '\n' )
	};
};
/**
 * The task itself
 * @param {Grunt} grunt The grunt object
 */
module.exports = function ( grunt ) {

	var path = require( "path" );

	grunt.registerMultiTask( 'template-module', 'Compile underscore templates to JST file that can be exposed as a module', function () {
		var sys = require( "lodash" );
		var beautifier = require( "node-beautify" );

		var defaultOptions = {
			namespace        : null,
			templateSettings : {
				client       : true,
				compileDebug : true
			},
			lintExpr         : {
				//				unused : false, asi : true, expr : true
			},
			module           : true,
			requireProvider  : true,
			provider         : "underscore",
			processName      : function ( name ) {
				return name;
			},
			useStrict        : false,
			single 			 : false,
			prettify         : false,
			prettifyOptions  : {
				indentSize : 2
			}
		};

		var options = sys.extend( {}, defaultOptions, this.options() );
		var templateProvider = require( options.provider );

		grunt.verbose.writeflags( options, 'Options' );

		var nsInfo;
		// we want to turn module off in the event other setting would collide with it
		if ( options.amdWrapper || !sys.isEmpty( options.namespace ) ) {
			options.module = false;
		}
		if ( options.module ) {
			options.amdWrapper = false;
			nsInfo = {
				namespace   : "exports",
				declaration : ""
			};
		} else {
			options.module = false;
			options.requireProvider = false;
			options.namespace = options.namespace || "JST";
			nsInfo = getNamespaceDeclaration( options.namespace );
		}

		var output = [];
		var compiled, templateName;
		var oneSource = (this.files.length === 1);

		this.files.forEach( function ( f ) {

			sys.each( f.src, function ( srcFile ) {
				var fpath;
				if ( f.cwd ) {
					fpath = path.resolve( f.cwd, srcFile );
				} else {
					fpath = srcFile;
				}
				var src = grunt.file.read( fpath );
				try {
					if ( options.provider === "ejs" ) {
						options.templateSettings.filename = fpath;
						compiled = templateProvider.compile( src, options.templateSettings );
					} else {
						compiled = templateProvider.template( src, false, options.templateSettings ).source;
					}

					if ( options.single === true && options.module === true && oneSource )
					{
						output.push( "module.exports = " + compiled + ";" );
					}
					else
					{
						templateName = options.processName( srcFile );
						output.push( nsInfo.namespace + "[" + JSON.stringify( templateName ) + "] = " + compiled + ";" );
					}
				} catch ( e ) {
					grunt.log.error( e );
					grunt.fail.warn( "file failed to compile." );
				}
			} );

			if ( output.length > 0 ) {
				if ( !sys.isEmpty( nsInfo.declaration ) ) {
					output.unshift( nsInfo.declaration );
				}
				if ( options.amdWrapper ) {
					var amdDefine = typeof options.amdWrapper === "string" ? options.amdWrapper : "define(function(){";
					output.unshift( amdDefine );
					output.push( "  return " + nsInfo.namespace + ";\n});" );
				} else if ( options.requireProvider ) {
					output.unshift( ["var _ = require('" + options.provider + "');"] );
				}
				if ( options.lintExpr && !sys.isEmpty( options.lintExpr ) ) {
					var lintlines = sys.map( options.lintExpr, function ( v, k ) {
						return k + ", " + v;
					} );
					output.push( "\n jshint " + lintlines.join( " " ) );
				}

				if ( options.useStrict ) {
					output.unshift( '"use strict;"\n' );
				}

				var contents = output.join( "\n" );
				if ( options.prettify ) {
					contents = beautifier.beautifyJs( contents, options.prettifyOptions );
				}

				grunt.file.write( f.dest, contents );
				grunt.log.writeln( "File '" + f.dest + "' created." );

			}
		} );

	} );
};
<|endoftext|>


<commit_before>module.exports = {
  webpack: {
    output: {
      publicPath: '',
    },
  },
};
<commit_msg>Delete craco config<commit_after><|endoftext|>


<commit_before>import Vue from 'vue';
import component from '~/jobs/components/trigger_block.vue';
import mountComponent from '../../helpers/vue_mount_component_helper';

describe('Trigger block', () => {
  const Component = Vue.extend(component);
  let vm;

  afterEach(() => {
    vm.$destroy();
  });

  describe('with short token', () => {
    it('renders short token', () => {
      vm = mountComponent(Component, {
        trigger: {
          short_token: '0a666b2',
        },
      });

      expect(vm.$el.querySelector('.js-short-token').textContent).toContain('0a666b2');
    });
  });

  describe('without short token', () => {
    it('does not render short token', () => {
      vm = mountComponent(Component, { trigger: {} });

      expect(vm.$el.querySelector('.js-short-token')).toBeNull();
    });
  });

  describe('with variables', () => {
    describe('hide/reveal variables', () => {
      it('should toggle variables on click', done => {
        vm = mountComponent(Component, {
          trigger: {
            short_token: 'bd7e',
            variables: [
              { key: 'UPLOAD_TO_GCS', value: 'false', public: false },
              { key: 'UPLOAD_TO_S3', value: 'true', public: false },
            ],
          },
        });

        vm.$el.querySelector('.js-reveal-variables').click();

        vm.$nextTick()
          .then(() => {
            expect(vm.$el.querySelector('.js-build-variables')).not.toBeNull();
            expect(vm.$el.querySelector('.js-reveal-variables').textContent.trim()).toEqual(
              'Hide values',
            );
            expect(vm.$el.querySelector('.js-build-variables').textContent).toContain(
              'UPLOAD_TO_GCS',
            );

            expect(vm.$el.querySelector('.js-build-variables').textContent).toContain('false');
            expect(vm.$el.querySelector('.js-build-variables').textContent).toContain(
              'UPLOAD_TO_S3',
            );

            expect(vm.$el.querySelector('.js-build-variables').textContent).toContain('true');

            vm.$el.querySelector('.js-reveal-variables').click();
          })
          .then(vm.$nextTick)
          .then(() => {
            expect(vm.$el.querySelector('.js-reveal-variables').textContent.trim()).toEqual(
              'Reveal values',
            );
            expect(vm.$el.querySelector('.js-build-variables').textContent).toContain(
              'UPLOAD_TO_GCS',
            );
            expect(vm.$el.querySelector('.js-build-value').textContent).toContain('••••••');
            expect(vm.$el.querySelector('.js-build-variables').textContent).toContain(
              'UPLOAD_TO_S3',
            );
            expect(vm.$el.querySelector('.js-build-value').textContent).toContain('••••••');
          })
          .then(done)
          .catch(done.fail);
      });
    });
  });

  describe('without variables', () => {
    it('does not render variables', () => {
      vm = mountComponent(Component, { trigger: {} });

      expect(vm.$el.querySelector('.js-reveal-variables')).toBeNull();
      expect(vm.$el.querySelector('.js-build-variables')).toBeNull();
    });
  });
});
<commit_msg>Fixes linting errors<commit_after>import Vue from 'vue';
import component from '~/jobs/components/trigger_block.vue';
import mountComponent from '../../helpers/vue_mount_component_helper';

describe('Trigger block', () => {
  const Component = Vue.extend(component);
  let vm;

  afterEach(() => {
    vm.$destroy();
  });

  describe('with short token', () => {
    it('renders short token', () => {
      vm = mountComponent(Component, {
        trigger: {
          short_token: '0a666b2',
        },
      });

      expect(vm.$el.querySelector('.js-short-token').textContent).toContain('0a666b2');
    });
  });

  describe('without short token', () => {
    it('does not render short token', () => {
      vm = mountComponent(Component, { trigger: {} });

      expect(vm.$el.querySelector('.js-short-token')).toBeNull();
    });
  });

  describe('with variables', () => {
    describe('hide/reveal variables', () => {
      it('should toggle variables on click', done => {
        vm = mountComponent(Component, {
          trigger: {
            short_token: 'bd7e',
            variables: [
              { key: 'UPLOAD_TO_GCS', value: 'false', public: false },
              { key: 'UPLOAD_TO_S3', value: 'true', public: false },
            ],
          },
        });

        vm.$el.querySelector('.js-reveal-variables').click();

        vm.$nextTick()
          .then(() => {
            expect(vm.$el.querySelector('.js-build-variables')).not.toBeNull();
            expect(vm.$el.querySelector('.js-reveal-variables').textContent.trim()).toEqual(
              'Hide values',
            );

            expect(vm.$el.querySelector('.js-build-variables').textContent).toContain(
              'UPLOAD_TO_GCS',
            );

            expect(vm.$el.querySelector('.js-build-variables').textContent).toContain('false');
            expect(vm.$el.querySelector('.js-build-variables').textContent).toContain(
              'UPLOAD_TO_S3',
            );

            expect(vm.$el.querySelector('.js-build-variables').textContent).toContain('true');

            vm.$el.querySelector('.js-reveal-variables').click();
          })
          .then(vm.$nextTick)
          .then(() => {
            expect(vm.$el.querySelector('.js-reveal-variables').textContent.trim()).toEqual(
              'Reveal values',
            );

            expect(vm.$el.querySelector('.js-build-variables').textContent).toContain(
              'UPLOAD_TO_GCS',
            );

            expect(vm.$el.querySelector('.js-build-value').textContent).toContain('••••••');

            expect(vm.$el.querySelector('.js-build-variables').textContent).toContain(
              'UPLOAD_TO_S3',
            );

            expect(vm.$el.querySelector('.js-build-value').textContent).toContain('••••••');
          })
          .then(done)
          .catch(done.fail);
      });
    });
  });

  describe('without variables', () => {
    it('does not render variables', () => {
      vm = mountComponent(Component, { trigger: {} });

      expect(vm.$el.querySelector('.js-reveal-variables')).toBeNull();
      expect(vm.$el.querySelector('.js-build-variables')).toBeNull();
    });
  });
});
<|endoftext|>


<commit_before>define([
	"dojo/_base/declare","dijit/_WidgetBase","dojo/on",
	"dojo/dom-class",
	"dojo/text!./templates/SeqComparison.html","./AppBase","dojo/dom-construct",
        "dojo/_base/Deferred","dojo/aspect","dojo/_base/lang","dojo/domReady!","dijit/form/NumberTextBox",
	"dojo/query", "dojo/dom", "dijit/popup", "dijit/Tooltip", "dijit/Dialog", "dijit/TooltipDialog",
    "dojo/NodeList-traverse","../../WorkspaceManager", "dojo/store/Memory", "dojox/widget/Standby"
], function(
	declare, WidgetBase, on,
	domClass,
	Template,AppBase,domConstruct,
        Deferred,aspect,lang,domReady,NumberTextBox,query,
	dom, popup, Tooltip, Dialog, TooltipDialog, children,WorkspaceManager, Memory, Standby
){
	return declare([AppBase], {
		"baseClass": "App Assembly",
		templateString: Template,
		applicationName: "GenomeComparison",
		defaultPath: "",
		startingRows: 8,
		maxGenomes: 8,

		constructor: function(){
			this._selfSet=true;
			this.addedGenomes=0;
			this.genomeToAttachPt=["comp_genome_id"];
		},

        startup: function(){
                        var _self=this;
                        if (this._started) { return; }
			this.inherited(arguments);

			_self.defaultPath = WorkspaceManager.getDefaultFolder() || _self.activeWorkspacePath;
            _self.output_path.set('value', _self.defaultPath);

            this.emptyTable(this.genomeTable, this.startingRows);
			this.numgenomes.startup();
			this.advrow.turnedOn=(this.advrow.style.display!='none');
			on(this.advanced, 'click', lang.hitch(this, function(){
				this.advrow.turnedOn=(this.advrow.style.display!='none');
				if (! this.advrow.turnedOn){
					this.advrow.turnedOn=true;
					this.advrow.style.display='block';
					this.advicon.className="fa fa-caret-left fa-1";
				}
				else{
					this.advrow.turnedOn=false;
					this.advrow.style.display='none';
					this.advicon.className="fa fa-caret-down fa-1";
				}
			}));
            this._started=true;
		},

        emptyTable:function(target, rowLimit){
			for (i = 0; i < rowLimit; i++) {
				var tr =  target.insertRow(0);//domConstr.create("tr",{},this.genomeTableBody);
				var td = domConstruct.create('td', {innerHTML: "

"},tr);
				var td2 = domConstruct.create("td", {innerHTML: "

"},tr);
				var td3 = domConstruct.create("td", {innerHTML: "

"},tr);
			}
        },

		ingestAttachPoints: function(input_pts, target, req){
                        req = typeof req !== 'undefined' ? req : true;
			var success=1;
			input_pts.forEach(function(attachname){
				var cur_value=null;
				var incomplete =0;
				var browser_select=0;
				if(attachname == "read1" || attachname == "read2" || attachname == "single_end_libs"){
					cur_value=this[attachname].searchBox.value;//? "/_uuid/"+this[attachname].searchBox.value : "";
					//cur_value=this[attachname].searchBox.get('value');
					//incomplete=((cur_value.replace(/^.*[\\\/]/, '')).length==0);
					browser_select=1;
				}
				else if(attachname == "output_path"){
					cur_value=this[attachname].searchBox.value;//? "/_uuid/"+this[attachname].searchBox.value : "";
					//cur_value="/_uuid/"+this[attachname].searchBox.value;
					//cur_value=this[attachname].searchBox.get('value');
					browser_select=1;
				}
				else if(attachname == "comp_genome_id"){
					var compGenomeList = query(".genomedata");
            		var genomeIds=[];

					compGenomeList.forEach(function(item){
						genomeIds.push(item.genomeRecord.comp_genome_id)});

					cur_value=this[attachname].value;

					//console.log("genomeIds = " + genomeIds + " cur_value = " + cur_value + " index = " +genomeIds.indexOf(cur_value));
					if (genomeIds.length>0 && genomeIds.indexOf(cur_value) > -1)  // no same genome ids are allowed
					{
						success=0;
					}
				}
				else{
					cur_value=this[attachname].value;
				}

				console.log("cur_value=" + cur_value);

				if(typeof(cur_value) == "string"){
					target[attachname]=cur_value.trim();
				}
				else{
					target[attachname]=cur_value;
				}
				if(req && (!target[attachname] || incomplete)){
					if(browser_select){
						this[attachname].searchBox.validate(); //this should be whats done but it doesn't actually call the new validator
						this[attachname].searchBox._set("state","Error");
						this[attachname].focus=true;
					}
					success=0;
				}
				else{
					this[attachname]._set("state","");
				}
				if(target[attachname]!=""){
					target[attachname]= target[attachname] || undefined;
				}
				else if (target[attachname] == "true"){
					target[attachname]=true;
				}
				else if (target[attachname]=="false"){
					target[attachname]=false;
				}
			}, this);
			return(success);
		},

        onSuggestNameChange: function(){
            console.log("change genome name");
        },

        makeGenomeName:function(){
        	var name = this.comp_genome_id.get("displayedValue");
			var maxName=36;
			var display_name = name;
			if(name.length > maxName){
				display_name=name.substr(0,(maxName/2)-2)+"...."+name.substr((name.length-(maxName/2))+2);
			}

            return display_name;
        },

		increaseGenome: function(){
			this.addedGenomes= this.addedGenomes+1;
			this.numgenomes.set('value',Number(this.addedGenomes));

		},
		decreaseGenome: function(){
			this.addedGenomes = this.addedGenomes-1;
			this.numgenomes.set('value',Number(this.addedGenomes));
		},

		onAddGenome: function(){
			console.log("Create New Row", domConstruct);
			var lrec={};
			var chkPassed=this.ingestAttachPoints(this.genomeToAttachPt, lrec);
			console.log("chkPassed = " + chkPassed);
			if (chkPassed && this.addedGenomes < this.maxGenomes){
				var tr = this.genomeTable.insertRow(0);
				var td = domConstruct.create('td', {"class":"textcol genomedata", innerHTML:""},tr);
				td.genomeRecord=lrec;
				td.innerHTML="
"+this.makeGenomeName()+"
";
				var tdinfo=domConstruct.create("td", {innerHTML: ""},tr);
				var td2 = domConstruct.create("td", {innerHTML: ""},tr);
				if(this.addedGenomes < this.startingRows){
					this.genomeTable.deleteRow(-1);
				}
				var handle = on(td2, "click", lang.hitch(this,function(evt){
					console.log("Delete Row");
					domConstruct.destroy(tr);
					this.decreaseGenome();
					if (this.addedGenomes < this.startingRows){
						var ntr = this.genomeTable.insertRow(-1);
						var ntd = domConstruct.create('td', {innerHTML: "

"},ntr);
						var ntd2 = domConstruct.create("td", {innerHTML: "

"},ntr);
						var ntd3 = domConstruct.create("td", {innerHTML: "

"},ntr);
					}
					handle.remove();
				}));
				this.increaseGenome();
			}
			console.log(lrec);
		},

		getValues: function(){
			var seqcomp_values={};
			var values = this.inherited(arguments);
			var compGenomeList = query(".genomedata");
            var genomeIds=[];
            var userGenomes =[];

			genomeIds.push(values["ref_genome_id"]);
			compGenomeList.forEach(function(item){
				genomeIds.push(item.genomeRecord.comp_genome_id)});

			userGenomes.push(values["user_genomes"]);

			//console.log("compGenomeList = " + compGenomeList);
			//console.log("ref genome = " + values["ref_genome_id"]);

			seqcomp_values["genome_ids"]=genomeIds;
			seqcomp_values["user_genomes"]=userGenomes;
			seqcomp_values["reference_genome_index"]=1;
			seqcomp_values["min_seq_cov"]=values["min_seq_cov"]/100;
			seqcomp_values["max_e_val"]=values["max_e_val"];
			seqcomp_values["output_path"]=values["output_path"];
			seqcomp_values["output_file"]=values["output_file"];

			return seqcomp_values;
		}

	});
});

<commit_msg>handled empty user genome case<commit_after>define([
	"dojo/_base/declare","dijit/_WidgetBase","dojo/on",
	"dojo/dom-class",
	"dojo/text!./templates/SeqComparison.html","./AppBase","dojo/dom-construct",
        "dojo/_base/Deferred","dojo/aspect","dojo/_base/lang","dojo/domReady!","dijit/form/NumberTextBox",
	"dojo/query", "dojo/dom", "dijit/popup", "dijit/Tooltip", "dijit/Dialog", "dijit/TooltipDialog",
    "dojo/NodeList-traverse","../../WorkspaceManager", "dojo/store/Memory", "dojox/widget/Standby"
], function(
	declare, WidgetBase, on,
	domClass,
	Template,AppBase,domConstruct,
        Deferred,aspect,lang,domReady,NumberTextBox,query,
	dom, popup, Tooltip, Dialog, TooltipDialog, children,WorkspaceManager, Memory, Standby
){
	return declare([AppBase], {
		"baseClass": "App Assembly",
		templateString: Template,
		applicationName: "GenomeComparison",
		defaultPath: "",
		startingRows: 8,
		maxGenomes: 8,

		constructor: function(){
			this._selfSet=true;
			this.addedGenomes=0;
			this.genomeToAttachPt=["comp_genome_id"];
		},

        startup: function(){
                        var _self=this;
                        if (this._started) { return; }
			this.inherited(arguments);

			_self.defaultPath = WorkspaceManager.getDefaultFolder() || _self.activeWorkspacePath;
            _self.output_path.set('value', _self.defaultPath);

            this.emptyTable(this.genomeTable, this.startingRows);
			this.numgenomes.startup();
			this.advrow.turnedOn=(this.advrow.style.display!='none');
			on(this.advanced, 'click', lang.hitch(this, function(){
				this.advrow.turnedOn=(this.advrow.style.display!='none');
				if (! this.advrow.turnedOn){
					this.advrow.turnedOn=true;
					this.advrow.style.display='block';
					this.advicon.className="fa fa-caret-left fa-1";
				}
				else{
					this.advrow.turnedOn=false;
					this.advrow.style.display='none';
					this.advicon.className="fa fa-caret-down fa-1";
				}
			}));
            this._started=true;
		},

        emptyTable:function(target, rowLimit){
			for (i = 0; i < rowLimit; i++) {
				var tr =  target.insertRow(0);//domConstr.create("tr",{},this.genomeTableBody);
				var td = domConstruct.create('td', {innerHTML: "

"},tr);
				var td2 = domConstruct.create("td", {innerHTML: "

"},tr);
				var td3 = domConstruct.create("td", {innerHTML: "

"},tr);
			}
        },

		ingestAttachPoints: function(input_pts, target, req){
                        req = typeof req !== 'undefined' ? req : true;
			var success=1;
			input_pts.forEach(function(attachname){
				var cur_value=null;
				var incomplete =0;
				var browser_select=0;
				if(attachname == "read1" || attachname == "read2" || attachname == "single_end_libs"){
					cur_value=this[attachname].searchBox.value;//? "/_uuid/"+this[attachname].searchBox.value : "";
					//cur_value=this[attachname].searchBox.get('value');
					//incomplete=((cur_value.replace(/^.*[\\\/]/, '')).length==0);
					browser_select=1;
				}
				else if(attachname == "output_path"){
					cur_value=this[attachname].searchBox.value;//? "/_uuid/"+this[attachname].searchBox.value : "";
					//cur_value="/_uuid/"+this[attachname].searchBox.value;
					//cur_value=this[attachname].searchBox.get('value');
					browser_select=1;
				}
				else if(attachname == "comp_genome_id"){
					var compGenomeList = query(".genomedata");
            		var genomeIds=[];

					compGenomeList.forEach(function(item){
						genomeIds.push(item.genomeRecord.comp_genome_id)});

					cur_value=this[attachname].value;

					//console.log("genomeIds = " + genomeIds + " cur_value = " + cur_value + " index = " +genomeIds.indexOf(cur_value));
					if (genomeIds.length>0 && genomeIds.indexOf(cur_value) > -1)  // no same genome ids are allowed
					{
						success=0;
					}
				}
				else{
					cur_value=this[attachname].value;
				}

				console.log("cur_value=" + cur_value);

				if(typeof(cur_value) == "string"){
					target[attachname]=cur_value.trim();
				}
				else{
					target[attachname]=cur_value;
				}
				if(req && (!target[attachname] || incomplete)){
					if(browser_select){
						this[attachname].searchBox.validate(); //this should be whats done but it doesn't actually call the new validator
						this[attachname].searchBox._set("state","Error");
						this[attachname].focus=true;
					}
					success=0;
				}
				else{
					this[attachname]._set("state","");
				}
				if(target[attachname]!=""){
					target[attachname]= target[attachname] || undefined;
				}
				else if (target[attachname] == "true"){
					target[attachname]=true;
				}
				else if (target[attachname]=="false"){
					target[attachname]=false;
				}
			}, this);
			return(success);
		},

        onSuggestNameChange: function(){
            console.log("change genome name");
        },

        makeGenomeName:function(){
        	var name = this.comp_genome_id.get("displayedValue");
			var maxName=36;
			var display_name = name;
			if(name.length > maxName){
				display_name=name.substr(0,(maxName/2)-2)+"...."+name.substr((name.length-(maxName/2))+2);
			}

            return display_name;
        },

		increaseGenome: function(){
			this.addedGenomes= this.addedGenomes+1;
			this.numgenomes.set('value',Number(this.addedGenomes));

		},
		decreaseGenome: function(){
			this.addedGenomes = this.addedGenomes-1;
			this.numgenomes.set('value',Number(this.addedGenomes));
		},

		onAddGenome: function(){
			console.log("Create New Row", domConstruct);
			var lrec={};
			var chkPassed=this.ingestAttachPoints(this.genomeToAttachPt, lrec);
			console.log("chkPassed = " + chkPassed);
			if (chkPassed && this.addedGenomes < this.maxGenomes){
				var tr = this.genomeTable.insertRow(0);
				var td = domConstruct.create('td', {"class":"textcol genomedata", innerHTML:""},tr);
				td.genomeRecord=lrec;
				td.innerHTML="
"+this.makeGenomeName()+"
";
				var tdinfo=domConstruct.create("td", {innerHTML: ""},tr);
				var td2 = domConstruct.create("td", {innerHTML: ""},tr);
				if(this.addedGenomes < this.startingRows){
					this.genomeTable.deleteRow(-1);
				}
				var handle = on(td2, "click", lang.hitch(this,function(evt){
					console.log("Delete Row");
					domConstruct.destroy(tr);
					this.decreaseGenome();
					if (this.addedGenomes < this.startingRows){
						var ntr = this.genomeTable.insertRow(-1);
						var ntd = domConstruct.create('td', {innerHTML: "

"},ntr);
						var ntd2 = domConstruct.create("td", {innerHTML: "

"},ntr);
						var ntd3 = domConstruct.create("td", {innerHTML: "

"},ntr);
					}
					handle.remove();
				}));
				this.increaseGenome();
			}
			console.log(lrec);
		},

		getValues: function(){
			var seqcomp_values={};
			var values = this.inherited(arguments);
			var compGenomeList = query(".genomedata");
            var genomeIds=[];
            var userGenomes =[];

			genomeIds.push(values["ref_genome_id"]);
			compGenomeList.forEach(function(item){
				genomeIds.push(item.genomeRecord.comp_genome_id)});

			if (values["user_genomes"])
			{
				userGenomes.push(values["user_genomes"]);
			}

			//console.log("compGenomeList = " + compGenomeList);
			//console.log("ref genome = " + values["ref_genome_id"]);

			seqcomp_values["genome_ids"]=genomeIds;
			if (userGenomes.length > 0)
			{
				seqcomp_values["user_genomes"]=userGenomes;
			}
			seqcomp_values["reference_genome_index"]=1;
			seqcomp_values["min_seq_cov"]=values["min_seq_cov"]/100;
			seqcomp_values["max_e_val"]=values["max_e_val"];
			seqcomp_values["output_path"]=values["output_path"];
			seqcomp_values["output_file"]=values["output_file"];

			return seqcomp_values;
		}

	});
});

<|endoftext|>


<commit_before>
((module) => {
	'use strict';

	var createClassFromSuper = require('simple-class-utils').createClass.super;
	var Root = require('./root.js').class;

	var _key_iterator = Symbol.iterator;

	module.exports = createClass;

	function createClass(Super, ...args) {

		class XIterable extends (typeof Super === 'function' ? Super : createClass.default) {

			forEach(callback) {
				for (let element of this) {
					callback(element, this);
				}
			}

			map(callback) {
				var result = new this.Array();
				this.forEach((element) => result.push(callback(element, this)));
				return result;
			}

			some(callback) {
				for (let element of this) {
					if (callback(element, this)) {
						return true;
					}
				}
				return false;
			}

			every(callback) {
				return !this.every((element) => !callback(element, this));
			}

			filter(callback) {
				var result = new this.Array();
				this.forEach((element) => callback(element, this) && result.push(element));
				return result;
			}

			most(callback, init) {
				for (let element of this) {
					if (callback(element, init, this)) {
						init = element;
					}
				}
				return init;
			}

			get min() {
				return this.most((challenger, champion) => challenger < champion, +Infinity);
			}

			get max() {
				return this.most((challenger, champion) => challenger > champion, -Infinity);
			}

			toArray() {
				return this.Array.from(this);
			}

			find(callback) {
				for (let element of this) {
					if (callback(element, this)) {
						return element;
					}
				}
			}

			search(callback) {
				for (let element of this) {
					if (callback(element, this)) {
						return new this.search.Result(element, this);
					}
				}
			}

		}

		((proto) => {
			proto.Array = Array;
			proto.search.Result = class extends Root {
				constructor(value, object) {
					this.value = value;
					this.object = object;
				}
			};
			var superproto = Object.getPrototypeOf(proto);
			makeMethodExists('join', function (...args) {
				return this.toArray().join(...args);
			});
			function makeMethodExists(fname, func) {
				if (typeof superproto[fname] !== 'function') {
					proto[fname] = func;
				}
			}
		})(XIterable.prototype);

		return createClassFromSuper(XIterable, ...args);

	}

	createClass.default = Root.IterableBased;

	createClass.fromGenerator = (gen, ...args) =>
		createClass(class extends createClass.fromGenerator.Root {
			constructor(...args) {
				super();
				var base = gen.apply(this, args);
				this[_key_iterator] = () => base;
			}
		}, ...args);

	createClass.fromGenerator.Root = createClassFromSuper(Root);

	createClass.Yield = createClass.fromGenerator(function * (base) {
		yield * base;
	});

})(module);
<commit_msg>add reduce()<commit_after>
((module) => {
	'use strict';

	var createClassFromSuper = require('simple-class-utils').createClass.super;
	var Root = require('./root.js').class;

	var _key_iterator = Symbol.iterator;

	module.exports = createClass;

	function createClass(Super, ...args) {

		class XIterable extends (typeof Super === 'function' ? Super : createClass.default) {

			forEach(callback) {
				for (let element of this) {
					callback(element, this);
				}
			}

			map(callback) {
				var result = new this.Array();
				this.forEach((element) => result.push(callback(element, this)));
				return result;
			}

			some(callback) {
				for (let element of this) {
					if (callback(element, this)) {
						return true;
					}
				}
				return false;
			}

			every(callback) {
				return !this.every((element) => !callback(element, this));
			}

			filter(callback) {
				var result = new this.Array();
				this.forEach((element) => callback(element, this) && result.push(element));
				return result;
			}

			reduce(callback, init) {
				this.forEach((element) => init = callback(init, element, this));
				return init;
			}

			most(callback, init) {
				for (let element of this) {
					if (callback(element, init, this)) {
						init = element;
					}
				}
				return init;
			}

			get min() {
				return this.most((challenger, champion) => challenger < champion, +Infinity);
			}

			get max() {
				return this.most((challenger, champion) => challenger > champion, -Infinity);
			}

			toArray() {
				return this.Array.from(this);
			}

			find(callback) {
				for (let element of this) {
					if (callback(element, this)) {
						return element;
					}
				}
			}

			search(callback) {
				for (let element of this) {
					if (callback(element, this)) {
						return new this.search.Result(element, this);
					}
				}
			}

		}

		((proto) => {
			proto.Array = Array;
			proto.search.Result = class extends Root {
				constructor(value, object) {
					this.value = value;
					this.object = object;
				}
			};
			var superproto = Object.getPrototypeOf(proto);
			makeMethodExists('join', function (...args) {
				return this.toArray().join(...args);
			});
			function makeMethodExists(fname, func) {
				if (typeof superproto[fname] !== 'function') {
					proto[fname] = func;
				}
			}
		})(XIterable.prototype);

		return createClassFromSuper(XIterable, ...args);

	}

	createClass.default = Root.IterableBased;

	createClass.fromGenerator = (gen, ...args) =>
		createClass(class extends createClass.fromGenerator.Root {
			constructor(...args) {
				super();
				var base = gen.apply(this, args);
				this[_key_iterator] = () => base;
			}
		}, ...args);

	createClass.fromGenerator.Root = createClassFromSuper(Root);

	createClass.Yield = createClass.fromGenerator(function * (base) {
		yield * base;
	});

})(module);
<|endoftext|>


<commit_before>// Showdown extensions definitions
var OdyMarkdown = function()
{
	var responsiveTablesBegin = {
		type: "output",
		regex: "
",
		replace: "

"
	};
	var responsiveTablesEnd = {
		type: "output",
		regex: "
",
		replace: "

"
	};
	var notes = {
		type: "lang",
		filter: function(text, c, o) {return filterCommand(text, "notes", notes_command);}
	};
	return [responsiveTablesBegin, responsiveTablesEnd, notes];
}

//Register extensions
showdown.extension("OdyMarkdown", OdyMarkdown);

// Generic command processing functions
function filterCommand(text, commandName, command)
{
	var start = text.indexOf("!" + commandName);
	while(start >= 0)
	{
		var argumentObject = {};
		var stop = 0;
		if(text.charAt(start + commandName.length + 1) === "[")
		{
			stop = text.indexOf("]", start + commandName.length + 2);
			var argumentString = text.substring(start + commandName.length + 2, stop);
			argumentObject = parseArguments(argumentString);
		}
		else
		{
			stop = start + commandName.length;
		}
		text = text.substring(0, start) + command(argumentObject) + text.substring(stop + 1, text.length)
		start = text.indexOf("!" + commandName);
	}
	return text;
}

function parseArguments(argumentString)
{
	var output = {};
	var list = argumentString.replace(/ /g,"").split(",");
	for(i = 0; i < list.length; ++i)
	{
		var tuple = list[i].split("=");
		if (tuple.length !== 2)
		{
			return {};
		}
		output[tuple[0]] = tuple[1];
	}
	return output;
}

// Specific commands
function notes_command(argumentObject)
{
	return "<textarea class=\"notes\" placeholder=\"Tvoje poznámky\"></textarea>";
}

<commit_msg>Links open in new tab by default<commit_after>// Showdown extensions definitions
var OdyMarkdown = function()
{
	var responsiveTablesBegin = {
		type: "output",
		regex: "
",
		replace: "

"
	};
	var responsiveTablesEnd = {
		type: "output",
		regex: "
",
		replace: "

"
	};
	var blankLinks = {
		type: "output",
		regex: "<a href",
		replace: "= 0)
	{
		var argumentObject = {};
		var stop = 0;
		if(text.charAt(start + commandName.length + 1) === "[")
		{
			stop = text.indexOf("]", start + commandName.length + 2);
			var argumentString = text.substring(start + commandName.length + 2, stop);
			argumentObject = parseArguments(argumentString);
		}
		else
		{
			stop = start + commandName.length;
		}
		text = text.substring(0, start) + command(argumentObject) + text.substring(stop + 1, text.length)
		start = text.indexOf("!" + commandName);
	}
	return text;
}

function parseArguments(argumentString)
{
	var output = {};
	var list = argumentString.replace(/ /g,"").split(",");
	for(i = 0; i < list.length; ++i)
	{
		var tuple = list[i].split("=");
		if (tuple.length !== 2)
		{
			return {};
		}
		output[tuple[0]] = tuple[1];
	}
	return output;
}

// Specific commands
function notes_command(argumentObject)
{
	return "<textarea class=\"notes\" placeholder=\"Tvoje poznámky\"></textarea>";
}

<|endoftext|>


<commit_before>import parser from 'cheerio-without-node-native'

export default function (html) {
  const $ = parser.load(html, {
    decodeEntities: true
  })
  const result = []
  const totalPage = parseInt($('.page li.disabled').last().prev().text() || 1)
  $('table tr').each(function (i, elem) {
    const $this = $(this)
    const info = {}
    // console.log($this.text())
    $this.find('td').each(function (j, elem) {
      const that = $(this)
      if (j === 0) {
        info.rank = that.text()
      } else if (j === 1) {
        info.avatar = that.find('img').attr('src')
        info.href = that.find('a').attr('href')
        info.psnid = that.find('a').attr('href').split('/').pop()
      } else if (j === 2) {
        info.content = `<div>${that.html().trim().replace(/<p>.*?<\/p>/,'')}</div>`
      } else if (j === 3) {
        info.exp = that.find('em').text()
        info.level = that.html().replace(/<em>.*?<\/em>/, '').trim()
      } else if (j === 4) {
        info.games = that.text()
      } else if (j === 5) {
        info.perfectRate = that.text()
      } else if (j === 6) {
        info.platinum = that.text()
      } else if (j === 7) {
        info.gold = that.text()
      } else if (j === 8) {
        info.silver = that.text()
      } else if (j === 9) {
        info.bronze = that.text()
      }
    })
    const text = $this.text()
    if (text.includes('Z币')) {
      info.type = 'zb'
    } else if (text.includes('N币')) {
      info.type = 'nb'
    } else if (text.includes('第一天签到')) {
      info.type = 'qidao'
    } else {
      info.type = 'general'
    }
    result.push(info)
  })

  return {
    list: result,
    totalPage: totalPage
  }
}<commit_msg>减少排行的解析循环次数以加快载入<commit_after>import parser from 'cheerio-without-node-native'

export default function (html) {
  const $ = parser.load(html, {
    decodeEntities: true
  })
  const result = []
  const totalPage = parseInt($('.page li.disabled').last().prev().text() || 1)
  $('table tr').each(function (i, elem) {
    const $this = $(this)
    const info = {}

    const text = $this.text()
    const arr = text.split('\n').map(item => item.trim()).filter(item => item)
    info.rank = arr[0]
    info.avatar = $this.find('img').attr('src')
    info.href = $this.find('a').attr('href')
    info.psnid = arr[1]
    info.exp = (arr[2].split('经验') || [])[1]
    info.level = (arr[2].split('经验') || [])[0]
    info.content = `<div>${$this.find('p').parent().html().trim().replace(/<p>.*?<\/p>/,'')}</div>`
    info.games = arr[3]
    info.perfectRate =arr[4]
    info.platinum = arr[5]
    info.gold = arr[6]
    info.silver = arr[7]
    info.bronze = arr[8]

    if (text.includes('Z币')) {
      info.type = 'zb'
    } else if (text.includes('N币')) {
      info.type = 'nb'
    } else if (text.includes('第一天签到')) {
      info.type = 'qidao'
    } else {
      info.type = 'general'
    }
    result.push(info)
  })

  return {
    list: result,
    totalPage: totalPage
  }
}<|endoftext|>


<commit_before>// FLUSHALL Redis before starting
require('../support/test_helper');

var assert = require('../support/assert');
var querystring = require('querystring');
var fs = require('fs');
var redis = require('redis');
var step = require('step');
var mapnik = require('mapnik');
var Windshaft = require('../../lib/windshaft');
var ServerOptions = require('../support/server_options');
var semver = require('semver');
var http = require('http');
var testClient = require('../support/test_client');

function rmdir_recursive_sync(dirname) {
  var files = fs.readdirSync(dirname);
  for (var i=0; i<files.length; ++i) {
    var f = dirname + "/" + files[i];
    var s = fs.lstatSync(f);
    if ( s.isFile() ) {
      fs.unlinkSync(f);
    }
    else {
        rmdir_recursive_sync(f);
    }
  }
}

suite('server_gettile', function() {

    ////////////////////////////////////////////////////////////////////
    //
    // SETUP
    //
    ////////////////////////////////////////////////////////////////////

    var server = new Windshaft.Server(ServerOptions);
    server.setMaxListeners(0);
    var redis_client = redis.createClient(ServerOptions.redis.port);
    var res_serv; // resources server
    var res_serv_status = { numrequests:0 }; // status of resources server
    var res_serv_port = 8033; // FIXME: make configurable ?

    var IMAGE_EQUALS_TOLERANCE_PER_MIL = 25;

    suiteSetup(function(done) {

      // Check that we start with an empty redis db
      redis_client.keys("*", function(err, matches) {

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

        assert.equal(matches.length, 0,
          "redis keys present at setup time on port " +
          ServerOptions.redis.port + ":\n" + matches.join("\n"));

        // Start a server to test external resources
        res_serv = http.createServer( function(request, response) {
            ++res_serv_status.numrequests;
            var filename = __dirname + '/../fixtures/markers' + request.url;
            fs.readFile(filename, "binary", function(err, file) {
              if ( err ) {
                response.writeHead(404, {'Content-Type': 'text/plain'});
                response.write("404 Not Found\n");
              } else {
                response.writeHead(200);
                response.write(file, "binary");
              }
              response.end();
            });
        });
        res_serv.listen(res_serv_port, done);

      });

    });

    function imageCompareFn(fixture, done) {
        return function(err, res) {
            if (err) {
                return done(err);
            }
            assert.imageEqualsFile(res.body, './test/fixtures/' + fixture, IMAGE_EQUALS_TOLERANCE_PER_MIL, done);
        };
    }

    ////////////////////////////////////////////////////////////////////
    //
    // GET TILE
    // --{
    ////////////////////////////////////////////////////////////////////

    test("get'ing a tile with default style should return an expected tile", function(done){
      testClient.getTile(testClient.defaultTableMapConfig('test_table'), 13, 4011, 3088,
          imageCompareFn('test_table_13_4011_3088.png', done)
      );
    });

    test.skip("response of get tile can be served by renderer cache",  function(done){
      var cb = Date.now();
      step(
        function get1 () {
          var next = this;
          assert.response(server, {
              url: '/database/windshaft_test/table/test_table/13/4011/3088.png?cache_buster=' + cb,
              method: 'GET',
              encoding: 'binary'
          },{}, function(res, err) { next(err, res); });
        },
        function check1(err, res) {
          if ( err ) {
              throw err;
          }
          assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body);
          var xwc = res.headers['x-windshaft-cache'];
          assert.ok(!xwc);
          return null;
        },
        function get2() {
          var next = this;
          assert.response(server, {
              url: '/database/windshaft_test/table/test_table/13/4011/3088.png?cache_buster=' + cb,
              method: 'GET',
              encoding: 'binary'
          },{}, function(res, err) { next(err, res); });
        },
        function check2(err, res) {
          if ( err ) {
              throw err;
          }
          assert.equal(res.statusCode, 200);
          var xwc = res.headers['x-windshaft-cache'];
          assert.ok(xwc);
          assert.ok(xwc > 0);
          return null;
        },
        function get3() {
          var next = this;
          assert.response(server, {
              url: '/database/windshaft_test/table/test_table/13/4011/3088.png',
              method: 'GET',
              encoding: 'binary'
          },{}, function(res, err) { next(err, res); });
        },
        function check3(err, res) {
          if ( err ) {
              throw err;
          }
          assert.equal(res.statusCode, 200);
          var xwc = res.headers['x-windshaft-cache'];
          assert.ok(xwc);
          assert.ok(xwc > 0);
          return null;
        },
        function get4() {
          var next = this;
          assert.response(server, {
              url: '/database/windshaft_test/table/test_table/13/4011/3088.png?cache_buster='+(cb+1),
              method: 'GET',
              encoding: 'binary'
          },{}, function(res, err) { next(err, res); });
        },
        function check4(err, res) {
          if ( err ) {
              throw err;
          }
          assert.equal(res.statusCode, 200);
          var xwc = res.headers['x-windshaft-cache'];
          assert.ok(!xwc);
          return null;
        },
        function finish(err) {
          done(err);
        }
      );
    });

    test("should not choke when queries end with a semicolon",  function(done){
        testClient.getTile(testClient.singleLayerMapConfig('SELECT * FROM test_table limit 2;'), 0, 0, 0, done);
    });

    test("should not choke when sql ends with a semicolon and some blanks",  function(done){
        testClient.getTile(testClient.singleLayerMapConfig('SELECT * FROM test_table limit 2; \t\n'), 0, 0, 0, done);
    });

    test("should not strip quoted semicolons within an sql query",  function(done){
        testClient.getTile(
            testClient.singleLayerMapConfig("SELECT * FROM test_table where name != ';\n'"), 0, 0, 0, done
        );
    });

    test.skip("get'ing two tiles with same configuration uses renderer cache",  function(done){
        // NOTE: mus tuse the same cache_buster
        var style = querystring.stringify({style: "#test_table{marker-fill: blue;marker-line-color: black;}"});
        assert.response(server, {
            url: '/database/windshaft_test/table/test_table/13/4011/3088.png?cache_buster=5&' + style,
            method: 'GET',
            encoding: 'binary'
        },{}, function(res){
            assert.ok(!res.headers.hasOwnProperty('x-windshaft-cache'),
                     "Did hit renderer cache on first time");
            assert.imageEqualsFile(res.body, './test/fixtures/test_table_13_4011_3088_styled.png', IMAGE_EQUALS_TOLERANCE_PER_MIL, function(err) {
                if (err) { done(err); return; }
                assert.response(server, {
                    url: '/database/windshaft_test/table/test_table/13/4011/3087.png?cache_buster=5&' + style,
                    method: 'GET',
                    encoding: 'binary'
                }, {},
                function(res){
                  assert.ok(res.headers.hasOwnProperty('x-windshaft-cache'),
                     "Did not hit renderer cache on second time");
                  done();
                });
             });
        });
    });

    var test_style_black_200 = "#test_table{marker-fill:black;marker-line-color:black;marker-width:5}";
    var test_style_black_210 = "#test_table{marker-fill:black;marker-line-color:black;marker-width:10}";

    test("get'ing a tile with url specified 2.0.0 style should return an expected tile",  function(done){
        testClient.getTile(testClient.defaultTableMapConfig('test_table', test_style_black_200, '2.0.0'),
            13, 4011, 3088, imageCompareFn('test_table_13_4011_3088_styled_black.png', done));
    });

    test("get'ing a tile with url specified 2.1.0 style should return an expected tile",  function(done){
        testClient.getTile(testClient.defaultTableMapConfig('test_table', test_style_black_210, '2.1.0'),
            13, 4011, 3088, imageCompareFn('test_table_13_4011_3088_styled_black.png', done));
    });

    // See http://github.com/CartoDB/Windshaft/issues/99
    test("unused directives are tolerated",  function(done){
        var style = "#test_table{point-transform: 'scale(100)';}";
        var sql = "SELECT 1 as cartodb_id, 'SRID=4326;POINT(0 0)'::geometry as the_geom";
        testClient.getTile(testClient.singleLayerMapConfig(sql, style), 0, 0, 0,
            imageCompareFn('test_default_mapnik_point.png', done));
    });

    // See http://github.com/CartoDB/Windshaft/issues/100
    var test_strictness = function(done){
        var style = querystring.stringify({
          style: "#test_table{point-transform: 'scale(100)';}",
          sql: "SELECT 1 as cartodb_id, 'SRID=3857;POINT(666 666)'::geometry as the_geom"
        });
        assert.response(server, {
            url: '/database/windshaft_test/table/test_table/0/0/0.png?strict=1&' + style,
            method: 'GET',
            encoding: 'binary'
        },{}, function(res){
            assert.equal(res.statusCode, 400);
            done();
        });
    };
    var test_strict_lbl = "unused directives are not tolerated if strict";
    if ( semver.satisfies(mapnik.versions.mapnik, '2.3.x') ) {
      // Strictness handling changed in 2.3.x, possibly a bug:
      // see http://github.com/mapnik/mapnik/issues/2301
      console.warn("Strictness test skipped due to http://github.com/mapnik/mapnik/issues/2301");
      test.skip(test_strict_lbl,  test_strictness);
    }
    else {
      test.skip(test_strict_lbl,  test_strictness);
    }

    test("beforeTileRender is called when the client request a tile",  function(done) {
        testClient.getTile(testClient.defaultTableMapConfig('test_table'), 6, 31, 24, function(err, res) {
            assert.equal(res.headers['x-beforetilerender'], 'called');
            done();
        });
    });

    test("afterTileRender is called when the client request a tile",  function(done) {
        testClient.getTile(testClient.defaultTableMapConfig('test_table'), 6, 31, 24, function(err, res) {
            assert.equal(res.headers['x-aftertilerender'], 'called');
            assert.equal(res.headers['x-aftertilerender2'], 'called');
            done();
        });
    });

    test('high cpu regression with mapnik <2.3.x', function(done) {
        var sql = [
            "SELECT 'my polygon name here' AS name,",
            "       st_envelope(st_buffer(st_transform(st_setsrid(st_makepoint(-26.6592894004,49.7990296995),4326),3857),10000000)) AS the_geom",
            "FROM generate_series(-6,6) x",
            "UNION ALL",
            "SELECT 'my marker name here' AS name,",
            "       st_transform(st_setsrid(st_makepoint(49.6042060319,-49.0522997372),4326),3857) AS the_geom",
            "FROM generate_series(-6,6) x"
        ].join(' ');

        var style = [
            '#test_table {marker-fill:#ff7;',
            '    marker-max-error:0.447492761618;',
            '    marker-line-opacity:0.659371340628;',
            '    marker-allow-overlap:true;',
            '    polygon-fill:green;',
            '    marker-spacing:0.0;',
            '    marker-width:4.0;',
            '    marker-height:18.0;',
            '    marker-opacity:0.942312062822;',
            '    line-color:green;',
            '    line-gamma:0.945973211092;',
            '    line-cap:square;',
            '    polygon-opacity:0.12576055992;',
            '    marker-type:arrow;',
            '    polygon-gamma:0.46354913107;',
            '    line-dasharray:33,23;',
            '    line-join:bevel;',
            '    marker-placement:line;',
            '    line-width:1.0;',
            '    marker-line-color:#ff7;',
            '    line-opacity:0.39403752154;',
            '    marker-line-width:3.0;',
            '}'
        ].join('');

        testClient.getTile(testClient.singleLayerMapConfig(sql, style), 13, 4011, 3088, done);
    });

    ////////////////////////////////////////////////////////////////////
    //
    // --}
    // TEARDOWN
    //
    ////////////////////////////////////////////////////////////////////

    suiteTeardown(function(done) {

      // Close the resources server
      res_serv.close();

      var errors = [];

      // Check that we left the redis db empty
      redis_client.keys("*", function(err, matches) {
          if ( err ) {
              errors.push(err);
          }
          try {
            assert.equal(matches.length, 0, "Left over redis keys:\n" + matches.join("\n"));
          } catch (err) {
            errors.push(err);
          }

          var cachedir = global.environment.millstone.cache_basedir;
          rmdir_recursive_sync(cachedir);

          redis_client.flushall(function() {
            done(errors.length ? new Error(errors) : null);
          });
      });

    });
});

<commit_msg>Re-enable conditional strict test<commit_after>// FLUSHALL Redis before starting
require('../support/test_helper');

var assert = require('../support/assert');
var querystring = require('querystring');
var fs = require('fs');
var redis = require('redis');
var step = require('step');
var mapnik = require('mapnik');
var Windshaft = require('../../lib/windshaft');
var ServerOptions = require('../support/server_options');
var semver = require('semver');
var http = require('http');
var testClient = require('../support/test_client');

function rmdir_recursive_sync(dirname) {
  var files = fs.readdirSync(dirname);
  for (var i=0; i<files.length; ++i) {
    var f = dirname + "/" + files[i];
    var s = fs.lstatSync(f);
    if ( s.isFile() ) {
      fs.unlinkSync(f);
    }
    else {
        rmdir_recursive_sync(f);
    }
  }
}

suite('server_gettile', function() {

    ////////////////////////////////////////////////////////////////////
    //
    // SETUP
    //
    ////////////////////////////////////////////////////////////////////

    var server = new Windshaft.Server(ServerOptions);
    server.setMaxListeners(0);
    var redis_client = redis.createClient(ServerOptions.redis.port);
    var res_serv; // resources server
    var res_serv_status = { numrequests:0 }; // status of resources server
    var res_serv_port = 8033; // FIXME: make configurable ?

    var IMAGE_EQUALS_TOLERANCE_PER_MIL = 25;

    suiteSetup(function(done) {

      // Check that we start with an empty redis db
      redis_client.keys("*", function(err, matches) {

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

        assert.equal(matches.length, 0,
          "redis keys present at setup time on port " +
          ServerOptions.redis.port + ":\n" + matches.join("\n"));

        // Start a server to test external resources
        res_serv = http.createServer( function(request, response) {
            ++res_serv_status.numrequests;
            var filename = __dirname + '/../fixtures/markers' + request.url;
            fs.readFile(filename, "binary", function(err, file) {
              if ( err ) {
                response.writeHead(404, {'Content-Type': 'text/plain'});
                response.write("404 Not Found\n");
              } else {
                response.writeHead(200);
                response.write(file, "binary");
              }
              response.end();
            });
        });
        res_serv.listen(res_serv_port, done);

      });

    });

    function imageCompareFn(fixture, done) {
        return function(err, res) {
            if (err) {
                return done(err);
            }
            assert.imageEqualsFile(res.body, './test/fixtures/' + fixture, IMAGE_EQUALS_TOLERANCE_PER_MIL, done);
        };
    }

    ////////////////////////////////////////////////////////////////////
    //
    // GET TILE
    // --{
    ////////////////////////////////////////////////////////////////////

    test("get'ing a tile with default style should return an expected tile", function(done){
      testClient.getTile(testClient.defaultTableMapConfig('test_table'), 13, 4011, 3088,
          imageCompareFn('test_table_13_4011_3088.png', done)
      );
    });

    test.skip("response of get tile can be served by renderer cache",  function(done){
      var cb = Date.now();
      step(
        function get1 () {
          var next = this;
          assert.response(server, {
              url: '/database/windshaft_test/table/test_table/13/4011/3088.png?cache_buster=' + cb,
              method: 'GET',
              encoding: 'binary'
          },{}, function(res, err) { next(err, res); });
        },
        function check1(err, res) {
          if ( err ) {
              throw err;
          }
          assert.equal(res.statusCode, 200, res.statusCode + ': ' + res.body);
          var xwc = res.headers['x-windshaft-cache'];
          assert.ok(!xwc);
          return null;
        },
        function get2() {
          var next = this;
          assert.response(server, {
              url: '/database/windshaft_test/table/test_table/13/4011/3088.png?cache_buster=' + cb,
              method: 'GET',
              encoding: 'binary'
          },{}, function(res, err) { next(err, res); });
        },
        function check2(err, res) {
          if ( err ) {
              throw err;
          }
          assert.equal(res.statusCode, 200);
          var xwc = res.headers['x-windshaft-cache'];
          assert.ok(xwc);
          assert.ok(xwc > 0);
          return null;
        },
        function get3() {
          var next = this;
          assert.response(server, {
              url: '/database/windshaft_test/table/test_table/13/4011/3088.png',
              method: 'GET',
              encoding: 'binary'
          },{}, function(res, err) { next(err, res); });
        },
        function check3(err, res) {
          if ( err ) {
              throw err;
          }
          assert.equal(res.statusCode, 200);
          var xwc = res.headers['x-windshaft-cache'];
          assert.ok(xwc);
          assert.ok(xwc > 0);
          return null;
        },
        function get4() {
          var next = this;
          assert.response(server, {
              url: '/database/windshaft_test/table/test_table/13/4011/3088.png?cache_buster='+(cb+1),
              method: 'GET',
              encoding: 'binary'
          },{}, function(res, err) { next(err, res); });
        },
        function check4(err, res) {
          if ( err ) {
              throw err;
          }
          assert.equal(res.statusCode, 200);
          var xwc = res.headers['x-windshaft-cache'];
          assert.ok(!xwc);
          return null;
        },
        function finish(err) {
          done(err);
        }
      );
    });

    test("should not choke when queries end with a semicolon",  function(done){
        testClient.getTile(testClient.singleLayerMapConfig('SELECT * FROM test_table limit 2;'), 0, 0, 0, done);
    });

    test("should not choke when sql ends with a semicolon and some blanks",  function(done){
        testClient.getTile(testClient.singleLayerMapConfig('SELECT * FROM test_table limit 2; \t\n'), 0, 0, 0, done);
    });

    test("should not strip quoted semicolons within an sql query",  function(done){
        testClient.getTile(
            testClient.singleLayerMapConfig("SELECT * FROM test_table where name != ';\n'"), 0, 0, 0, done
        );
    });

    test.skip("get'ing two tiles with same configuration uses renderer cache",  function(done){
        // NOTE: mus tuse the same cache_buster
        var style = querystring.stringify({style: "#test_table{marker-fill: blue;marker-line-color: black;}"});
        assert.response(server, {
            url: '/database/windshaft_test/table/test_table/13/4011/3088.png?cache_buster=5&' + style,
            method: 'GET',
            encoding: 'binary'
        },{}, function(res){
            assert.ok(!res.headers.hasOwnProperty('x-windshaft-cache'),
                     "Did hit renderer cache on first time");
            assert.imageEqualsFile(res.body, './test/fixtures/test_table_13_4011_3088_styled.png', IMAGE_EQUALS_TOLERANCE_PER_MIL, function(err) {
                if (err) { done(err); return; }
                assert.response(server, {
                    url: '/database/windshaft_test/table/test_table/13/4011/3087.png?cache_buster=5&' + style,
                    method: 'GET',
                    encoding: 'binary'
                }, {},
                function(res){
                  assert.ok(res.headers.hasOwnProperty('x-windshaft-cache'),
                     "Did not hit renderer cache on second time");
                  done();
                });
             });
        });
    });

    var test_style_black_200 = "#test_table{marker-fill:black;marker-line-color:black;marker-width:5}";
    var test_style_black_210 = "#test_table{marker-fill:black;marker-line-color:black;marker-width:10}";

    test("get'ing a tile with url specified 2.0.0 style should return an expected tile",  function(done){
        testClient.getTile(testClient.defaultTableMapConfig('test_table', test_style_black_200, '2.0.0'),
            13, 4011, 3088, imageCompareFn('test_table_13_4011_3088_styled_black.png', done));
    });

    test("get'ing a tile with url specified 2.1.0 style should return an expected tile",  function(done){
        testClient.getTile(testClient.defaultTableMapConfig('test_table', test_style_black_210, '2.1.0'),
            13, 4011, 3088, imageCompareFn('test_table_13_4011_3088_styled_black.png', done));
    });

    // See http://github.com/CartoDB/Windshaft/issues/99
    test("unused directives are tolerated",  function(done){
        var style = "#test_table{point-transform: 'scale(100)';}";
        var sql = "SELECT 1 as cartodb_id, 'SRID=4326;POINT(0 0)'::geometry as the_geom";
        testClient.getTile(testClient.singleLayerMapConfig(sql, style), 0, 0, 0,
            imageCompareFn('test_default_mapnik_point.png', done));
    });

    // See http://github.com/CartoDB/Windshaft/issues/100
    var test_strictness = function(done) {
        var nonStrictMapConfig = testClient.singleLayerMapConfig(
            "SELECT 1 as cartodb_id, 'SRID=3857;POINT(666 666)'::geometry as the_geom",
            "#test_table{point-transform: 'scale(100)';}"
        );
        testClient.withLayergroup(nonStrictMapConfig, function(err, requestTile, finish) {
            var options = {
                statusCode: 400,
                contentType: 'application/json; charset=utf-8'
            };
            requestTile('/0/0/0.png?strict=1', options, function() {
                finish(done);
            });
        });
    };
    var test_strict_lbl = "unused directives are not tolerated if strict";
    if ( semver.satisfies(mapnik.versions.mapnik, '2.3.x') ) {
      // Strictness handling changed in 2.3.x, possibly a bug:
      // see http://github.com/mapnik/mapnik/issues/2301
      console.warn("Strictness test skipped due to http://github.com/mapnik/mapnik/issues/2301");
      test.skip(test_strict_lbl,  test_strictness);
    }
    else {
      test(test_strict_lbl,  test_strictness);
    }

    test("beforeTileRender is called when the client request a tile",  function(done) {
        testClient.getTile(testClient.defaultTableMapConfig('test_table'), 6, 31, 24, function(err, res) {
            assert.equal(res.headers['x-beforetilerender'], 'called');
            done();
        });
    });

    test("afterTileRender is called when the client request a tile",  function(done) {
        testClient.getTile(testClient.defaultTableMapConfig('test_table'), 6, 31, 24, function(err, res) {
            assert.equal(res.headers['x-aftertilerender'], 'called');
            assert.equal(res.headers['x-aftertilerender2'], 'called');
            done();
        });
    });

    test('high cpu regression with mapnik <2.3.x', function(done) {
        var sql = [
            "SELECT 'my polygon name here' AS name,",
            "       st_envelope(st_buffer(st_transform(st_setsrid(st_makepoint(-26.6592894004,49.7990296995),4326),3857),10000000)) AS the_geom",
            "FROM generate_series(-6,6) x",
            "UNION ALL",
            "SELECT 'my marker name here' AS name,",
            "       st_transform(st_setsrid(st_makepoint(49.6042060319,-49.0522997372),4326),3857) AS the_geom",
            "FROM generate_series(-6,6) x"
        ].join(' ');

        var style = [
            '#test_table {marker-fill:#ff7;',
            '    marker-max-error:0.447492761618;',
            '    marker-line-opacity:0.659371340628;',
            '    marker-allow-overlap:true;',
            '    polygon-fill:green;',
            '    marker-spacing:0.0;',
            '    marker-width:4.0;',
            '    marker-height:18.0;',
            '    marker-opacity:0.942312062822;',
            '    line-color:green;',
            '    line-gamma:0.945973211092;',
            '    line-cap:square;',
            '    polygon-opacity:0.12576055992;',
            '    marker-type:arrow;',
            '    polygon-gamma:0.46354913107;',
            '    line-dasharray:33,23;',
            '    line-join:bevel;',
            '    marker-placement:line;',
            '    line-width:1.0;',
            '    marker-line-color:#ff7;',
            '    line-opacity:0.39403752154;',
            '    marker-line-width:3.0;',
            '}'
        ].join('');

        testClient.getTile(testClient.singleLayerMapConfig(sql, style), 13, 4011, 3088, done);
    });

    ////////////////////////////////////////////////////////////////////
    //
    // --}
    // TEARDOWN
    //
    ////////////////////////////////////////////////////////////////////

    suiteTeardown(function(done) {

      // Close the resources server
      res_serv.close();

      var errors = [];

      // Check that we left the redis db empty
      redis_client.keys("*", function(err, matches) {
          if ( err ) {
              errors.push(err);
          }
          try {
            assert.equal(matches.length, 0, "Left over redis keys:\n" + matches.join("\n"));
          } catch (err) {
            errors.push(err);
          }

          var cachedir = global.environment.millstone.cache_basedir;
          rmdir_recursive_sync(cachedir);

          redis_client.flushall(function() {
            done(errors.length ? new Error(errors) : null);
          });
      });

    });
});

<|endoftext|>