<commit_before>/// <reference path="../lib/jquery-2.1.1.min.js" />
/// <reference path="../lib/qunit-git.js" />
/*
 * This file is part of "ZenQuery", (c) Kenshin The Battōsai (Sudarsan Balaji), 2014.
 *
 * "ZenQuery" is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * "ZenQuery" is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with "ZenQuery".  If not, see <http://www.gnu.org/licenses/>.
 *
 */

(function (window) {

    //'use strict';

    var ZenQuery,
        config,
        // For IE, to prevent Invalid Calling Object error on toString.call(obj)
        toString = Object.prototype.toString,
        hasOwn = Object.prototype.hasOwnProperty;

    ZenQuery = {

        // Returns the element name found in the zencoding string
        name: function (string) {
            if (arguments.length !== 1) {
                ZenQuery.incorrectArgs();
            }
            if (!ZenQuery.is('string', string)) {
                ZenQuery.invalidArgs();
            }
            var matches = config.matches,
                names = string.match(matches.name);
            if (ZenQuery.is('null', names)) {
                return 'div';
            }
            return names.join('');
        },

        // Returns the zencoding string with attributes removed
        // Helpful because data in the attributes might interfere with selection
        // eg: [href="http://thebattosai.in/#"]
        noAttributes: function (string) {
            if (arguments.length !== 1) {
                ZenQuery.incorrectArgs();
            }
            if (!ZenQuery.is('string', string)) {
                ZenQuery.invalidArgs();
            }
            var matches = config.matches;
            return string.replace(matches.attributes.all, '');
        },

        // Returns the classes found in the zencoding string as an array
        classes: function (string) {
            if (arguments.length !== 1) {
                ZenQuery.incorrectArgs();
            }
            if (!ZenQuery.is('string', string)) {
                ZenQuery.invalidArgs();
            }
            var matches = config.matches,
                classes = ZenQuery.noAttributes(string).match(matches.classes);
            if (ZenQuery.is('null', classes)) {
                return [];
            }
            classes = classes.join(' ').replace(/\./g, '').split(' ');
            return classes;
        },

        // Returns the id string found in the zencoding string
        id: function (string) {
            if (arguments.length !== 1) {
                ZenQuery.incorrectArgs();
            }
            if (!ZenQuery.is('string', string)) {
                ZenQuery.invalidArgs();
            }
            var matches = config.matches,
                id = ZenQuery.noAttributes(string).match(matches.id);
            if (ZenQuery.is('null', id)) {
                return '';
            }
            id = id.join(' ').replace('#', '');
            return id;
        },

        // Returns attributes found in the zencoding string as an object with key value pairs
        attributes: function (string) {
            if (arguments.length !== 1) {
                ZenQuery.incorrectArgs();
            }
            if (!ZenQuery.is('string', string)) {
                ZenQuery.invalidArgs();
            }
            var matches = config.matches.attributes,
                attributes = string.match(matches.all),
                array = [],
                key = '',
                name = matches.name,
                value = '',
                data = matches.value;
            if (ZenQuery.is('null', attributes)) {
                return {};
            }
            attributes = attributes.join('').replace(/\]\[/g, ' ');
            array = attributes.match(matches.single);
            if (ZenQuery.is('null', array)) {
                return {};
            }
            attributes = {};
            for (var i in array) {
                array[i] = ZenQuery.trim(array[i]);
                key = array[i].match(name);
                if (ZenQuery.is('null', key)) {
                    continue;
                }
                value = array[i].match(data);
                if (ZenQuery.is('null', value)) {
                    value = [''];
                }
                attributes[key.join('')] = value.join('').replace(/^('|")/, '').replace(/('|")$/, '');
            }
            return attributes;
        },

        // Returns an element from a zen coding string
        element: function(string) {
            if (arguments.length !== 1) {
                ZenQuery.incorrectArgs();
            }
            if (!ZenQuery.is('string', string)) {
                ZenQuery.invalidArgs();
            }
            var element = {},
                defaults = ZenQuery.config.element,
                id = ZenQuery.id(string),
                classes = ZenQuery.classes(string);
            element.name = ZenQuery.name(string);
            element.attributes = ZenQuery.attributes(string);
            if (id) {
                ZenQuery.extend(true, element.attributes, { id: id });
            }
            if (classes.length !== 0 && classes[0]!=='') {
                if (!element.attributes['class']) {
                    element.attributes['class'] = classes.join(' ');
                } else {
                    element.attributes['class'] += ' ' + classes.join(' ');
                }
            }
            return ZenQuery.extend(true, {}, defaults, element);
        },

        // Adds a child to an element
        add: function (element, child) {
            if (arguments.length < 1 || arguments.length > 2)
                ZenQuery.incorrectArgs();
            if (!ZenQuery.is('object', element))
                ZenQuery.invalidArgs();
            child = child || ZenQuery.extend(true, {}, ZenQuery.config.element);
            child.parent = element;
            element.children.push(child);
            return child;
        },

        // Returns a dom from a zen coding string
        dom: function(string) {
            if (arguments.length != 1) {
                ZenQuery.incorrectArgs();
            }
            if (!ZenQuery.is('string', string)) {
                ZenQuery.invalidArgs();
            }
            var root = ZenQuery.extend(true, {}, ZenQuery.config.element);
            var context = ZenQuery.add(root);

        },

        // Returns the string representation of html of an element
        html: function(element) {
            if (arguments.length !== 1)
                ZenQuery.incorrectArgs();
            if (!ZenQuery.is('object', element)
                || !ZenQuery.has('name', element)
                || !ZenQuery.has('attributes', element))
                ZenQuery.invalidArgs();
            var html = '',
                sortedkeys = [];
            html += '<' + element.name;
            for (var key in element.attributes)
                sortedkeys.push(key);
            sortedkeys.sort();
            for(var i in sortedkeys)
                html += ' ' + sortedkeys[i] + '="' + element.attributes[sortedkeys[i]] + '"';
            html += '></' + element.name + '>';
            return html;
        },

        // Renders a given zen coding string as html
        render: function (string) {
            if (arguments.length !== 1) {
                ZenQuery.incorrectArgs();
            }
            if (!ZenQuery.is('string', string)) {
                ZenQuery.invalidArgs();
            }
            return ZenQuery.html(ZenQuery.dom(string));
        },
    };

    // Check if Object Has Key
    function has (key, object) {
        if (!ZenQuery.is('array', object) && !ZenQuery.is('object', object)) {
            return false;
        }
        return hasOwn.call(object, key);
    };

    // Safe object type checking
    function is (type, obj) {
        return objectType(obj) === type;
    };

    // Object Type
    function objectType (obj) {
        if (typeof obj === "undefined") {
            return "undefined";
        }

        // Consider: typeof null === object
        if (obj === null) {
            return "null";
        }

        var match = toString.call(obj).match(/^\[object\s(.*)\]$/),
            type = match && match[1] || "";

        switch (type) {
            case "Number":
                if (isNaN(obj)) {
                    return "nan";
                }
                return "number";
            case "String":
            case "Boolean":
            case "Array":
            case "Date":
            case "RegExp":
            case "Function":
                return type.toLowerCase();
        }
        if (typeof obj === "object") {
            return "object";
        }
        return undefined;
    };

    // Incorrect Number of Arguments
    function incorrectArgs() {
        throw new Error('Incorrect Number of Arguments');
    };

    // Invalid Arguments
    function invalidArgs() {
        throw new Error('Invalid Arguments');
    };

    // Trim
    function trim(text) {
        return text == null ?
            "" :
            (text + "").replace(config.matches.trim, "");
    };

    // Extend
    function extend() {
        var options, name, src, copy, copyIsArray, clone,
            target = arguments[0] || {},
            i = 1,
            length = arguments.length,
            deep = false;

        // Handle a deep copy situation
        if (typeof target === "boolean") {
            deep = target;

            // skip the boolean and the target
            target = arguments[i] || {};
            i++;
        }

        // Handle case when target is a string or something (possible in deep copy)
        if (typeof target !== "object" && !is('function', target)) {
            target = {};
        }

        // extend ZenQuery itself if only one argument is passed
        if (i === length) {
            target = this;
            i--;
        }

        for (; i < length; i++) {
            // Only deal with non-null/undefined values
            if ((options = arguments[i]) != null) {
                // Extend the base object
                for (name in options) {
                    src = target[name];
                    copy = options[name];

                    // Prevent never-ending loop
                    if (target === copy) {
                        continue;
                    }

                    // Recurse if we're merging plain objects or arrays
                    if (deep && copy && (is('object', copy) || (copyIsArray = is('array', copy)))) {
                        if (copyIsArray) {
                            copyIsArray = false;
                            clone = src && is('array', src) ? src : [];

                        } else {
                            clone = src && is('object', src) ? src : {};
                        }

                        // Never move original objects, clone them
                        target[name] = extend(deep, clone, copy);

                        // Don't bring in undefined values
                    } else if (copy !== undefined) {
                        target[name] = copy;
                    }
                }
            }
        }

        // Return the modified object
        return target;
    };

    // Config
    config = {
        // RegEx-es thanks to http://regexpal.com/
        // And RegEx Magic http://www.regexmagic.com/
        matches: {
            element: {
                // Capture Groups: If Element, Name, Id, Classes with dots, Attributes
                complete: /( |\+|\^|>|([a-z]+)?(?:#([a-z-]+))?((?:\.[a-z-]+)*)((?:\[(?:[a-z-]+(?:="(?:\\.|[^\n\r"\\])*")?[\t ]?)+\])*))/g,
                // Capture Group: ClassName
                classes: /\.([a-z-]+)/g,
                // Capture Groups: Name, Value
                attributes: /([a-z-]+)(?:="((?:\\.|[^\n\r"\\])*)")?/g,
            },
            trim: /^[\x20\t\r\n\f]+|((?:^|[^\\])(?:\\.)*)[\x20\t\r\n\f]+$/g,
        },
        element: {
            parent: null,
            name: '',
            attributes: {},
            children: [],
        },
        pairs: {
            '[': ']',
            '(': ')',
            '{': '}'
        },
        operators: {
            nesting: {
                '>': 'child',
                '+': 'sibling',
                '^': 'climb',
                '*': 'multiply',
                '(': 'open',
                ')': 'close',
            },
            attribute: {
                '#': 'id',
                '.': 'class',
                '[': 'start',
                ']': 'stop',
                '$': 'number',
                '$@': 'sort-start',
                '$#': 'iterate'
            },
            text: {
                '{': 'write',
                '}': 'done',
                'c{': 'comment'
            },
            data: {
                '!': 'parse',
            }
        }
    };

    // Add stuff to ZenQuery
    extend(ZenQuery, {

        // Additions
        extend: extend,
        config: config,
        has: has,
        is: is,
        objectType: objectType,
        incorrectArgs: incorrectArgs,
        invalidArgs: invalidArgs,
        trim: trim,
    });

    // For browser, export only select globals
    if (typeof window !== "undefined" && window != null) {
        (function() {
            var
                // Map over ZenQuery in case of overwrite
                _ZenQuery = window.ZenQuery,

                // Map over the $Z in case of overwrite
                _$Z = window.$Z;

            ZenQuery.noConflict = function(deep) {
                if (window.$Z === ZenQuery) {
                    window.$Z = _$Z;
                }
                if (deep && window.ZenQuery === ZenQuery) {
                    window.ZenQuery = _ZenQuery;
                }
                return ZenQuery;
            };

            window.ZenQuery = window.$Z = ZenQuery;
            return ZenQuery;
        })();
    }

    // Get a reference to the global object, like window in browsers
}((function () {
    return this;
})()));<commit_msg>Added Utility Methods<commit_after>/// <reference path="../lib/jquery-2.1.1.min.js" />
/// <reference path="../lib/qunit-git.js" />
/*
 * This file is part of "ZenQuery", (c) Kenshin The Battōsai (Sudarsan Balaji), 2014.
 *
 * "ZenQuery" is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * "ZenQuery" is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with "ZenQuery".  If not, see <http://www.gnu.org/licenses/>.
 *
 */

(function (window) {

    //'use strict';

    var ZenQuery,
        config,
        objProto = Object.prototype,
        arrayProto = Array.prototype,
        // For IE, to prevent Invalid Calling Object error on toString.call(obj)
        toString = objProto.toString,
        nativeMap = arrayProto.map,
        nativeIndexOf = arrayProto.indexOf,
        nativeSome = arrayProto.some,
        nativeForEach = arrayProto.forEach,
        nativeEvery = arrayProto.every,
        nativeIsArray = arrayProto.isArray,
        push = arrayProto.push,
        concat = arrayProto.concat,
        emptyObj = {},
        isArray,
        hasOwn = objProto.hasOwnProperty;

    ZenQuery = {

        // Returns the classes found in a classes zencoding string partial as an array
        classes: function (string) {
            if (arguments.length !== 1) {
                ZenQuery.incorrectArgs();
            }
            if (!ZenQuery.is('string', string)) {
                ZenQuery.invalidArgs();
            }
            var matches = config.matches,
                classes = ZenQuery.noAttributes(string).match(matches.classes);
            if (ZenQuery.is('null', classes)) {
                return [];
            }
            classes = classes.join(' ').replace(/\./g, '').split(' ');
            return classes;
        },

        // Returns attributes found in an attributes zencoding string partial as an object with key value pairs
        attributes: function (string) {
            if (arguments.length !== 1) {
                ZenQuery.incorrectArgs();
            }
            if (!ZenQuery.is('string', string)) {
                ZenQuery.invalidArgs();
            }
            var matches = config.matches.attributes,
                attributes = string.match(matches.all),
                array = [],
                key = '',
                name = matches.name,
                value = '',
                data = matches.value;
            if (ZenQuery.is('null', attributes)) {
                return {};
            }
            attributes = attributes.join('').replace(/\]\[/g, ' ');
            array = attributes.match(matches.single);
            if (ZenQuery.is('null', array)) {
                return {};
            }
            attributes = {};
            for (var i in array) {
                array[i] = ZenQuery.trim(array[i]);
                key = array[i].match(name);
                if (ZenQuery.is('null', key)) {
                    continue;
                }
                value = array[i].match(data);
                if (ZenQuery.is('null', value)) {
                    value = [''];
                }
                attributes[key.join('')] = value.join('').replace(/^('|")/, '').replace(/('|")$/, '');
            }
            return attributes;
        },

        // Returns an element from a zen coding string
        element: function(string) {
            if (arguments.length !== 1) {
                ZenQuery.incorrectArgs();
            }
            if (!ZenQuery.is('string', string)) {
                ZenQuery.invalidArgs();
            }
            var element = {},
                defaults = ZenQuery.config.element,
                id = ZenQuery.id(string),
                classes = ZenQuery.classes(string);
            element.name = ZenQuery.name(string);
            element.attributes = ZenQuery.attributes(string);
            if (id) {
                ZenQuery.extend(true, element.attributes, { id: id });
            }
            if (classes.length !== 0 && classes[0]!=='') {
                if (!element.attributes['class']) {
                    element.attributes['class'] = classes.join(' ');
                } else {
                    element.attributes['class'] += ' ' + classes.join(' ');
                }
            }
            return ZenQuery.extend(true, {}, defaults, element);
        },

        // Adds a child to an element
        add: function (element, child) {
            if (arguments.length < 1 || arguments.length > 2)
                ZenQuery.incorrectArgs();
            if (!ZenQuery.is('object', element))
                ZenQuery.invalidArgs();
            child = child || ZenQuery.extend(true, {}, ZenQuery.config.element);
            child.parent = element;
            element.children.push(child);
            return child;
        },

        // Returns a dom from a zen coding string
        dom: function(string) {
            if (arguments.length != 1) {
                ZenQuery.incorrectArgs();
            }
            if (!ZenQuery.is('string', string)) {
                ZenQuery.invalidArgs();
            }
            var root = ZenQuery.extend(true, {}, ZenQuery.config.element);
            var context = ZenQuery.add(root);

        },

        // Returns the string representation of html of an element
        html: function(element) {
            if (arguments.length !== 1)
                ZenQuery.incorrectArgs();
            if (!ZenQuery.is('object', element)
                || !ZenQuery.has('name', element)
                || !ZenQuery.has('attributes', element))
                ZenQuery.invalidArgs();
            var html = '',
                sortedkeys = [];
            html += '<' + element.name;
            for (var key in element.attributes)
                sortedkeys.push(key);
            sortedkeys.sort();
            for(var i in sortedkeys)
                html += ' ' + sortedkeys[i] + '="' + element.attributes[sortedkeys[i]] + '"';
            html += '></' + element.name + '>';
            return html;
        },

        // Renders a given zen coding string as html
        render: function (string) {
            if (arguments.length !== 1) {
                ZenQuery.incorrectArgs();
            }
            if (!ZenQuery.is('string', string)) {
                ZenQuery.invalidArgs();
            }
            return ZenQuery.html(ZenQuery.dom(string));
        },
    };

    // Check if Object Has Key
    function has (key, object) {
        if (!ZenQuery.is('array', object) && !ZenQuery.is('object', object)) {
            return false;
        }
        return hasOwn.call(object, key);
    };

    // Safe object type checking
    function is (type, obj) {
        return objectType(obj) === type;
    };

    // Object Type
    function objectType (obj) {
        if (typeof obj === "undefined") {
            return "undefined";
        }

        // Consider: typeof null === object
        if (obj === null) {
            return "null";
        }

        var match = toString.call(obj).match(/^\[object\s(.*)\]$/),
            type = match && match[1] || "";

        switch (type) {
            case "Number":
                if (isNaN(obj)) {
                    return "nan";
                }
                return "number";
            case "String":
            case "Boolean":
            case "Array":
            case "Date":
            case "RegExp":
            case "Function":
                return type.toLowerCase();
        }
        if (typeof obj === "object") {
            return "object";
        }
        return undefined;
    };

    // IsArray
    isArray = nativeIsArray || function (obj) {
        return is('array', obj);
    };

    // Incorrect Number of Arguments
    function incorrectArgs() {
        throw new Error('Incorrect Number of Arguments');
    };

    // Invalid Arguments
    function invalidArgs() {
        throw new Error('Invalid Arguments');
    };

    // Trim
    function trim(text) {
        return text == null ?
            "" :
            (text + "").replace(config.matches.trim, "");
    };

    // Each
    function each(obj, iterator, context) {
        if (obj == null) return;
        if (nativeForEach && obj.forEach === nativeForEach) {
            obj.forEach(iterator, context);
        } else if (obj.length === +obj.length) {
            for (var i = 0, l = obj.length; i < l; i++) {
                if (iterator.call(context, obj[i], i, obj) === emptyObj) return;
            }
        } else {
            for (var key in obj) {
                if (has(key, obj)) {
                    if (iterator.call(context, obj[key], key, obj) === emptyObj) return;
                }
            }
        }
    };

    // Map
    function map(obj, iterator, context) {
        var results = [];
        if (obj == null) return results;
        if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
        each(obj, function(value, index, list) {
            results.push(iterator.call(context, value, index, list));
        });
        return results;
    };

    // Identity
    function identity(value) {
        return value;
    };

    // Any
    function any(obj, iterator, context) {
        iterator || (iterator = identity);
        var result = false;
        if (is('null', obj)) return result;
        if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
        each(obj, function(value, index, list) {
            if (result || (result = iterator.call(context, value, index, list))) return emptyObj;
        });
        return !!result;
    };

    // Contains
    function contains(obj, target) {
        if (obj == null) return false;
        if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
        return any(obj, function(value) {
            return value === target;
        });
    };

    // Unique
    function unique(array, isSorted, iterator, context) {
        if (is('function', isSorted)) {
            context = iterator;
            iterator = isSorted;
            isSorted = false;
        }
        var initial = iterator ? map(array, iterator, context) : array;
        var results = [];
        var seen = [];
        each(initial, function (value, index) {
            if (isSorted ? (!index || seen[seen.length - 1] !== value) : contains(seen, value)) {
                seen.push(value);
                results.push(array[index]);
            }
        });
        return results;
    };

    // Every
    function every(obj, iterator, context) {
        iterator || (iterator = identity);
        var result = true;
        if (is('null', obj)) return result;
        if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
        each(obj, function(value, index, list) {
            if (!(result = result && iterator.call(context, value, index, list))) return emptyObj;
        });
        return !!result;
    };

    // Flatten
    function flatten(input, shallow, output) {
        output || (output = []);
        if (shallow && every(input, isArray)) {
            return concat.apply(output, input);
        }
        each(input, function (value) {
            if (is('array',value) || is('object',value)) {
                shallow ? push.apply(output, value) : flatten(value, shallow, output);
            } else {
                output.push(value);
            }
        });
        return output;
    };

    // Union
    function union() {
        return unique(flatten(arguments, true));
    };

    // Extend
    function extend() {
        var options, name, src, copy, copyIsArray, clone,
            target = arguments[0] || {},
            i = 1,
            length = arguments.length,
            deep = false;

        // Handle a deep copy situation
        if (typeof target === "boolean") {
            deep = target;

            // skip the boolean and the target
            target = arguments[i] || {};
            i++;
        }

        // Handle case when target is a string or something (possible in deep copy)
        if (typeof target !== "object" && !is('function', target)) {
            target = {};
        }

        // extend ZenQuery itself if only one argument is passed
        if (i === length) {
            target = this;
            i--;
        }

        for (; i < length; i++) {
            // Only deal with non-null/undefined values
            if ((options = arguments[i]) != null) {
                // Extend the base object
                for (name in options) {
                    src = target[name];
                    copy = options[name];

                    // Prevent never-ending loop
                    if (target === copy) {
                        continue;
                    }

                    // Recurse if we're merging plain objects or arrays
                    if (deep && copy && (is('object', copy) || (copyIsArray = is('array', copy)))) {
                        if (copyIsArray) {
                            copyIsArray = false;
                            clone = src && is('array', src) ? src : [];

                        } else {
                            clone = src && is('object', src) ? src : {};
                        }

                        // Never move original objects, clone them
                        target[name] = extend(deep, clone, copy);

                        // Don't bring in undefined values
                    } else if (copy !== undefined) {
                        target[name] = copy;
                    }
                }
            }
        }

        // Return the modified object
        return target;
    };

    // Config
    config = {
        // RegEx-es thanks to http://regexpal.com/
        // And RegEx Magic http://www.regexmagic.com/
        matches: {
            element: {
                // Capture Groups: If Element, Name, Id, Classes with dots, Attributes
                complete: /( |\+|\^|>|([a-z]+)?(?:#([a-z-]+))?((?:\.[a-z-]+)*)((?:\[(?:[a-z-]+(?:="(?:\\.|[^\n\r"\\])*")?[\t ]?)+\])*))/g,
                // Capture Group: ClassName
                classes: /\.([a-z-]+)/g,
                // Capture Groups: Name, Value
                attributes: /([a-z-]+)(?:="((?:\\.|[^\n\r"\\])*)")?/g,
            },
            trim: /^[\x20\t\r\n\f]+|((?:^|[^\\])(?:\\.)*)[\x20\t\r\n\f]+$/g,
        },
        element: {
            parent: null,
            name: '',
            attributes: {},
            children: [],
        },
        pairs: {
            '[': ']',
            '(': ')',
            '{': '}'
        },
        operators: {
            nesting: {
                '>': 'child',
                '+': 'sibling',
                '^': 'climb',
                '*': 'multiply',
                '(': 'open',
                ')': 'close',
            },
            attribute: {
                '#': 'id',
                '.': 'class',
                '[': 'start',
                ']': 'stop',
                '$': 'number',
                '$@': 'sort-start',
                '$#': 'iterate'
            },
            text: {
                '{': 'write',
                '}': 'done',
                'c{': 'comment'
            },
            data: {
                '!': 'parse',
            }
        }
    };

    // Add stuff to ZenQuery
    extend(ZenQuery, {

        // Additions
        extend: extend,
        config: config,
        has: has,
        is: is,
        objectType: objectType,
        isArray: isArray,
        incorrectArgs: incorrectArgs,
        invalidArgs: invalidArgs,
        trim: trim,
        each: each,
        map: map,
        identity: identity,
        any: any,
        contains: contains,
        unique: unique,
        every: every,
        flatten: flatten,
        union: union,
    });

    // For browser, export only select globals
    if (typeof window !== "undefined" && window != null) {
        (function() {
            var
                // Map over ZenQuery in case of overwrite
                _ZenQuery = window.ZenQuery,

                // Map over the $Z in case of overwrite
                _$Z = window.$Z;

            ZenQuery.noConflict = function(deep) {
                if (window.$Z === ZenQuery) {
                    window.$Z = _$Z;
                }
                if (deep && window.ZenQuery === ZenQuery) {
                    window.ZenQuery = _ZenQuery;
                }
                return ZenQuery;
            };

            window.ZenQuery = window.$Z = ZenQuery;
            return ZenQuery;
        })();
    }

    // Get a reference to the global object, like window in browsers
}((function () {
    return this;
})()));<|endoftext|>


<commit_before>/*eslint-disable */

var prompt = require('prompt');
var chalk = require('chalk');
var fs = require('fs');
var path = require('path');
var spawn = require('child_process').spawn;
var configFile = path.join(__dirname, 'app/js/modules/config.js');

console.log(chalk.cyan('This utility will walk you through setting up the Kinvey AngularJS Social Connect App.'));
console.log(chalk.cyan('Please refer to http://devcenter.kinvey.com/angularjs for more information. Defaults are shown next to the question.'))
console.log(chalk.cyan('Press ^C at any time to quite.'));
console.log('');

// Customize the prompt
prompt.message = '';
prompt.delimiter = '';

// Start the prompt
prompt.start();

// Get appKey, appSecret, and redirectUri
prompt.get({
  properties: {
    appKey: {
      description: 'What is your app key?',
      required: true
    },
    appSecret: {
      description: 'What is your app secret?',
      required: true
    },
    apiHostname: {
      description: 'What is the API hostname?',
      default: 'https://baas.kinvey.com'
    },
    facebookAppId: {
      description: 'What is your Facebook applications app id?',
    }
  }
}, function(err, result) {
  if (err) {
    console.log(chalk.red(err));
    return;
  }

  result.facebookAppId = result.facebookAppId || '';

  var configFileData = '' +
    'var module = angular.module(\'config\', []);\n' +
    'module.constant(\'kinveyConfig\', {\n' +
    '  appKey: \'' + result.appKey + '\',\n' +
    '  appSecret: \'' + result.appSecret + '\',\n' +
    '  apiHostName: \'' + result.apiHostname + '\'\n' +
    '});'\'\n' +
    'window.facebookAppId = \'' + result.facebookAppId + '\'\n';

  // Write config file
  fs.writeFile(configFile, configFileData, function(err) {
    if (err) {
      console.log(chalk.red(err));
      return;
    }
  });
});
<commit_msg>Fixing error in install.js<commit_after>/*eslint-disable */

var prompt = require('prompt');
var chalk = require('chalk');
var fs = require('fs');
var path = require('path');
var spawn = require('child_process').spawn;
var configFile = path.join(__dirname, 'app/js/modules/config.js');

console.log(chalk.cyan('This utility will walk you through setting up the Kinvey AngularJS Social Connect App.'));
console.log(chalk.cyan('Please refer to http://devcenter.kinvey.com/angularjs for more information. Defaults are shown next to the question.'))
console.log(chalk.cyan('Press ^C at any time to quite.'));
console.log('');

// Customize the prompt
prompt.message = '';
prompt.delimiter = '';

// Start the prompt
prompt.start();

// Get appKey, appSecret, and redirectUri
prompt.get({
  properties: {
    appKey: {
      description: 'What is your app key?',
      required: true
    },
    appSecret: {
      description: 'What is your app secret?',
      required: true
    },
    apiHostname: {
      description: 'What is the API hostname?',
      default: 'https://baas.kinvey.com'
    },
    facebookAppId: {
      description: 'What is your Facebook applications app id?'
    }
  }
}, function(err, result) {
  if (err) {
    console.log(chalk.red(err));
    return;
  }

  result.facebookAppId = result.facebookAppId || '';

  var configFileData = '' +
    'var module = angular.module(\'config\', []);\n' +
    'module.constant(\'kinveyConfig\', {\n' +
    '  appKey: \'' + result.appKey + '\',\n' +
    '  appSecret: \'' + result.appSecret + '\',\n' +
    '  apiHostName: \'' + result.apiHostname + '\'\n' +
    '});\n' +
    'window.facebookAppId = \'' + result.facebookAppId + '\'\n';

  // Write config file
  fs.writeFile(configFile, configFileData, function(err) {
    if (err) {
      console.log(chalk.red(err));
      return;
    }
  });
});
<|endoftext|>


<commit_before>'use strict'

var cp = require('child_process')
var fs = require('fs')
var http = require('http')
var https = require('https')
var path = require('path')
var url = require('url')
var rimraf = require('rimraf').sync
var AdmZip = require('adm-zip')

fs.existsSync = fs.existsSync || path.existsSync

var libPath = path.join(__dirname, 'lib', 'casperjs')
var tmpPath = path.join(__dirname, 'tmp')
var downloadUrl = 'https://github.com/n1k0/casperjs/archive/1.0.3.zip'

function isCasperInstalled(notInstalledCallback) {
    findInstalledCasper(function(path, version) {
        if (path) {
            console.log("Use already installed Casperjs.");
            console.log("  Version: " + stdout);
            console.log("  Path:    " + pathStdout);
            fs.symlinkSync(pathStdout.replace(/\s/, ''), './casperjs');
        } else {
            console.log("Casperjs not installed.  Installing.");
            notInstalledCallback();
        }
    });
}

function findInstalledCasper(foundCallback) {
    // Note that "which" doesn't work on windows...
    cp.exec("which casperjs", function(error, path, stderr) {
        if (path) {
            cp.exec("casperjs --version", function(error, version, stderr) {
                foundCallback(path.trim(), version.trim());
            }
        } else {
            foundCallback();
        }
    });
}

function tidyUp() {
    rimraf(tmpPath);
}

function unzipTheZippedFile() {
    var zip = new AdmZip(path.join(tmpPath, 'archive.zip'));
    zip.extractAllTo(libPath, true);

    if (process.platform != 'win32') {
        var pathToCommand = path.join(libPath, 'casperjs-1.0.3', 'bin', 'casperjs');
        fs.symlinkSync(pathToCommand, './casperjs');
        var stat = fs.statSync(pathToCommand);
        if (!(stat.mode & 64)) {
            fs.chmodSync(pathToCommand, '755')
        }
    }
    tidyUp();
}

function downloadZipFromGithub() {
    var file = fs.createWriteStream(path.join(tmpPath, "archive.zip"));
    var lengthSoFar = 0;
    var request = https.get(downloadUrl, function(response) {
        if (response.statusCode === 301 || response.statusCode === 302) {
            downloadUrl = response.headers.location;
            downloadZipFromGithub();
        } else {
            response.pipe(file);
            response.on('data', function(chunk) {
                console.log('Receiving ' + Math.floor((lengthSoFar += chunk.length) / 1024) + 'K...' );
            }).
                on('end', unzipTheZippedFile).
                on('error', function(e) {
                    console.log('An error occured whilst trying to download Casper.JS ' + e.message);
                    tidyUp();
                });
        }
    });
    request.on('error', function(e) {
        console.log('An error occured whilst trying to download Casper.JS ' + e.message);
        tidyUp();
    });
}

isCasperInstalled(function() {
    if (!fs.existsSync(tmpPath)) {
        fs.mkdirSync(tmpPath);
    }
    rimraf(libPath);

    downloadZipFromGithub();
});
<commit_msg>Fix typo<commit_after>'use strict'

var cp = require('child_process')
var fs = require('fs')
var http = require('http')
var https = require('https')
var path = require('path')
var url = require('url')
var rimraf = require('rimraf').sync
var AdmZip = require('adm-zip')

fs.existsSync = fs.existsSync || path.existsSync

var libPath = path.join(__dirname, 'lib', 'casperjs')
var tmpPath = path.join(__dirname, 'tmp')
var downloadUrl = 'https://github.com/n1k0/casperjs/archive/1.0.3.zip'

function isCasperInstalled(notInstalledCallback) {
    findInstalledCasper(function(path, version) {
        if (path) {
            console.log("Use already installed Casperjs.");
            console.log("  Version: " + stdout);
            console.log("  Path:    " + pathStdout);
            fs.symlinkSync(pathStdout.replace(/\s/, ''), './casperjs');
        } else {
            console.log("Casperjs not installed.  Installing.");
            notInstalledCallback();
        }
    });
}

function findInstalledCasper(foundCallback) {
    // Note that "which" doesn't work on windows...
    cp.exec("which casperjs", function(error, path, stderr) {
        if (path) {
            cp.exec("casperjs --version", function(error, version, stderr) {
                foundCallback(path.trim(), version.trim());
            });
        } else {
            foundCallback();
        }
    });
}

function tidyUp() {
    rimraf(tmpPath);
}

function unzipTheZippedFile() {
    var zip = new AdmZip(path.join(tmpPath, 'archive.zip'));
    zip.extractAllTo(libPath, true);

    if (process.platform != 'win32') {
        var pathToCommand = path.join(libPath, 'casperjs-1.0.3', 'bin', 'casperjs');
        fs.symlinkSync(pathToCommand, './casperjs');
        var stat = fs.statSync(pathToCommand);
        if (!(stat.mode & 64)) {
            fs.chmodSync(pathToCommand, '755')
        }
    }
    tidyUp();
}

function downloadZipFromGithub() {
    var file = fs.createWriteStream(path.join(tmpPath, "archive.zip"));
    var lengthSoFar = 0;
    var request = https.get(downloadUrl, function(response) {
        if (response.statusCode === 301 || response.statusCode === 302) {
            downloadUrl = response.headers.location;
            downloadZipFromGithub();
        } else {
            response.pipe(file);
            response.on('data', function(chunk) {
                console.log('Receiving ' + Math.floor((lengthSoFar += chunk.length) / 1024) + 'K...' );
            }).
                on('end', unzipTheZippedFile).
                on('error', function(e) {
                    console.log('An error occured whilst trying to download Casper.JS ' + e.message);
                    tidyUp();
                });
        }
    });
    request.on('error', function(e) {
        console.log('An error occured whilst trying to download Casper.JS ' + e.message);
        tidyUp();
    });
}

isCasperInstalled(function() {
    if (!fs.existsSync(tmpPath)) {
        fs.mkdirSync(tmpPath);
    }
    rimraf(libPath);

    downloadZipFromGithub();
});
<|endoftext|>


<commit_before>#!/usr/bin/env node

'use strict';

var fs             = require('fs');
var shell          = require('shelljs');
var inquirer       = require('inquirer');
var defaultValues  = require('./src/config');
var configFilename = defaultValues.directories.user + '/config.json';
var themesAvailable= fs.readdirSync(defaultValues.directories.theme);

if (themesAvailable.length < 1) {
  throw new Error('No themes found');
}

var i;

for (var i = 2; i < process.argv.length; i++) {
  switch (process.argv[i]) {
    case '--only-new':
      if (! defaultValues.notInitialized) {
        console.log('`config.json` already present, start without `--only-new` to overwrite configuration.');
        process.exit(0);
      }
      break;
  }
}

defaultValues.imageSizes = defaultValues.imageSizes.map(function(i){
  return i.join('x');
});

var questions = [
  {
    type: 'input',
    name: 'name',
    message: 'The name of your site',
    default: defaultValues.name,
    validate: function(v) {
      return v ? true : 'Please supply at least a short name for your site.';
    }
  },{
    type: 'list',
    name: 'theme',
    message: 'Choose theme',
    default: defaultValues.theme,
    choices: themesAvailable,
    when: function(answers) {
      return (themesAvailable.length > 1);
    }
  },{
    type: 'input',
    name: 'baseUrl',
    message: 'Domain of your site, starting with `http`',
    default: defaultValues.baseUrl,
    validate: function(v) {
      return v.match(/^http(s)?:\/\/\S+$/) ? true : 'Please supply a valid url, starting with `http://`.';
    },
    filter: function(v) {
      return v.replace(/\/$/,'');
    }
  },{
    type: 'input',
    name: 'basePath',
    message: 'Base URL path, usually just `/`',
    default: defaultValues.basePath,
    validate: function(v) {
      return v.match(/^[a-zA-Z0-9\.\/_-]+$/) ? true : 'Please supply a valid path, at least `/`.';
    },
    filter: function(v) {
      return v.replace(/^([^\/])/,'/$1').replace(/([^\/])$/,'$1/');
    }
  },{
    type: 'input',
    name: 'description',
    message: 'A short description of your blog (optional)',
    default: defaultValues.description
  },{
    type: 'input',
    name: 'language',
    message: 'Standard language of your blog, like `en` for English',
    default: defaultValues.language,
    validate: function(v) {
      return v.match(/^[a-zA-Z\-]+$/) ? true : 'Please supply a valid two-letter language code like `en`, `es`, `fr` or `de`.';
    },
    filter: function(v) {
      return v.toLowerCase();
    }
  },{
    type: 'input',
    name: 'itemsPerPage',
    message: 'How many articles per page?',
    default: defaultValues.itemsPerPage,
    validate: function(v) {
      return Number(v)> 0 ? true : 'Please supply a positive number.';
    },
    filter: function(v) {
      return Number(v);
    }
  },{
    type: 'checkbox',
    name: 'imageSizes',
    message: 'What image sizes will be used?',
    default: defaultValues.imageSizes,
    choices: [
      "180x180",
      "240x240",
      "320x320",
      "640x640",
      new inquirer.Separator(),
      "320x240",
      "640x480",
      "1024x768",
      "1280x1024",
      new inquirer.Separator(),
      "400x225",
      "800x450",
      "1024x576",
      "1280x720",
      new inquirer.Separator()
    ]
  },{
    type: 'input',
    name: 'defaultAuthor',
    message: 'Default name of author',
    default: defaultValues.defaultAuthor.name,
    validate: function(v) {
      return v ? true : 'Please supply at least a short name for your site.';
    }
  },{
    type: 'input',
    name: 'defaultAuthorEmail',
    message: 'Default email address of author',
    default: defaultValues.defaultAuthor.email,
    validate: function(v) {
      return (v.match(/^\S+@\S+$/)) ? true : 'Please supply a valid email address.';
    }
  },{
    type: 'input',
    name: 'faviconBaseUrl',
    message: 'Base-URL of favicons (optional)',
    default: defaultValues.faviconBaseUrl,
    validate: function(v) {
      return (!v || v.match(/^http(s)?:\/\/\S+\/$/)) ? true : 'Please supply a valid url, starting with `http://` and ending with `/` - or leave field empty.';
    }
  },{
    type: 'checkbox',
    name: 'faviconSizes',
    message: 'What favicon sizes will be used?',
    default: defaultValues.faviconSizes,
    choices: [
      "96x96",
      "128x128",
      "144x144",
      "196x196",
      "256x256"
    ],
    when: function(answers) {
      return (answers.faviconBaseUrl);
    }
  },{
    type: 'input',
    name: 'ogImage',
    message: 'URL of standard teaser image (optional)',
    default: defaultValues.ogImage,
    validate: function(v) {
      return (!v || v.match(/^http(s)?:\/\/\S+$/)) ? true : 'Please supply a valid url, starting with `http://` or leave field empty.';
    },
    when: function(answers) {
      return (!answers.faviconBaseUrl);
    }
  },{
    type: 'input',
    name: 'twitterAccount',
    message: 'Twitter account name (optional)',
    default: defaultValues.twitterAccount,
    validate: function(v) {
      return (!v || v.match(/^[a-zA-z0-9_-]+$/)) ? true : 'Please supply a Twitter account name or leave field empty.';
    }
  },{
    type: 'input',
    name: 'themeColor',
    message: 'Basic color of your theme as hexcode (optional)',
    default: defaultValues.themeColor,
    validate: function(v) {
      return (!v || v.match(/^#[a-zA-z0-9]{3,6}$/)) ? true : 'Please supply a hex color code like `#fa647a`.';
    },
    filter: function(v) {
      return v.toLowerCase();
    }
  },{
    type: 'input',
    name: 'deployCmd',
    message: 'CLI command to copy files to your live server (optional)',
    default: defaultValues.deployCmd
  }
];

inquirer.prompt(questions).then(
  function (answers) {
    answers.theme = defaultValues.theme ? defaultValues.theme : themesAvailable[0];
    answers.defaultAuthor = {
      "email": answers.defaultAuthorEmail,
      "name": answers.defaultAuthor
    };
    delete answers.defaultAuthorEmail;
    answers.imageSizes = answers.imageSizes.map(function(i) {
      return i.split(/x/);
    });

    var ogImage = null;
    if (answers.faviconBaseUrl) {
      answers.icons = answers.faviconSizes.map(function(i) {
        ogImage = answers.faviconBaseUrl + 'favicon-'+i+'.png';
        return {
          src: ogImage,
          sizes: i,
        };
      });
    }
    if (!answers.ogImage && ogImage) {
      answers.ogImage = ogImage;
    }

    shell.mkdir('-p', defaultValues.directories.data);
    //console.log(answers);
    fs.writeFile(configFilename, JSON.stringify(answers, undefined, 2), function(err) {
      if (err) {
        console.error(configFilename + ' could not be written' ); process.exit(1);
      } else {
        console.log( configFilename + ' created');
      }
    });
    fs.writeFile(defaultValues.directories.htdocs+'/robots.txt', "# http://www.robotstxt.org/\n\nUser-agent: *\nDisallow: /google*.html\n\nSitemap: "+defaultValues.baseUrl+defaultValues.basePath+"sitemap.xml\n", function(err) {
      if (err) {
        console.error('htdocs/robots.txt' + ' could not be written' ); process.exit(1);
      } else {
        console.log( 'htdocs/robots.txt' + ' created');
      }
    });
  },
  function(err) { console.error(err); process.exit(1); }
);
<commit_msg>Installing CSS & JS on `install.js`<commit_after>#!/usr/bin/env node

'use strict';

var fs             = require('fs');
var shell          = require('shelljs');
var inquirer       = require('inquirer');
var defaultValues  = require('./src/config');
var configFilename = defaultValues.directories.user + '/config.json';
var themesAvailable= fs.readdirSync(defaultValues.directories.theme);

if (themesAvailable.length < 1) {
  throw new Error('No themes found');
}

var i;

for (var i = 2; i < process.argv.length; i++) {
  switch (process.argv[i]) {
    case '--only-new':
      if (! defaultValues.notInitialized) {
        console.log('`config.json` already present, start without `--only-new` to overwrite configuration.');
        process.exit(0);
      }
      break;
  }
}

defaultValues.imageSizes = defaultValues.imageSizes.map(function(i){
  return i.join('x');
});

var questions = [
  {
    type: 'input',
    name: 'name',
    message: 'The name of your site',
    default: defaultValues.name,
    validate: function(v) {
      return v ? true : 'Please supply at least a short name for your site.';
    }
  },{
    type: 'list',
    name: 'theme',
    message: 'Choose theme',
    default: defaultValues.theme,
    choices: themesAvailable,
    when: function(answers) {
      return (themesAvailable.length > 1);
    }
  },{
    type: 'input',
    name: 'baseUrl',
    message: 'Domain of your site, starting with `http`',
    default: defaultValues.baseUrl,
    validate: function(v) {
      return v.match(/^http(s)?:\/\/\S+$/) ? true : 'Please supply a valid url, starting with `http://`.';
    },
    filter: function(v) {
      return v.replace(/\/$/,'');
    }
  },{
    type: 'input',
    name: 'basePath',
    message: 'Base URL path, usually just `/`',
    default: defaultValues.basePath,
    validate: function(v) {
      return v.match(/^[a-zA-Z0-9\.\/_-]+$/) ? true : 'Please supply a valid path, at least `/`.';
    },
    filter: function(v) {
      return v.replace(/^([^\/])/,'/$1').replace(/([^\/])$/,'$1/');
    }
  },{
    type: 'input',
    name: 'description',
    message: 'A short description of your blog (optional)',
    default: defaultValues.description
  },{
    type: 'input',
    name: 'language',
    message: 'Standard language of your blog, like `en` for English',
    default: defaultValues.language,
    validate: function(v) {
      return v.match(/^[a-zA-Z\-]+$/) ? true : 'Please supply a valid two-letter language code like `en`, `es`, `fr` or `de`.';
    },
    filter: function(v) {
      return v.toLowerCase();
    }
  },{
    type: 'input',
    name: 'itemsPerPage',
    message: 'How many articles per page?',
    default: defaultValues.itemsPerPage,
    validate: function(v) {
      return Number(v)> 0 ? true : 'Please supply a positive number.';
    },
    filter: function(v) {
      return Number(v);
    }
  },{
    type: 'checkbox',
    name: 'imageSizes',
    message: 'What image sizes will be used?',
    default: defaultValues.imageSizes,
    choices: [
      "180x180",
      "240x240",
      "320x320",
      "640x640",
      new inquirer.Separator(),
      "320x240",
      "640x480",
      "1024x768",
      "1280x1024",
      new inquirer.Separator(),
      "400x225",
      "800x450",
      "1024x576",
      "1280x720",
      new inquirer.Separator()
    ]
  },{
    type: 'input',
    name: 'defaultAuthor',
    message: 'Default name of author',
    default: defaultValues.defaultAuthor.name,
    validate: function(v) {
      return v ? true : 'Please supply at least a short name for your site.';
    }
  },{
    type: 'input',
    name: 'defaultAuthorEmail',
    message: 'Default email address of author',
    default: defaultValues.defaultAuthor.email,
    validate: function(v) {
      return (v.match(/^\S+@\S+$/)) ? true : 'Please supply a valid email address.';
    }
  },{
    type: 'input',
    name: 'faviconBaseUrl',
    message: 'Base-URL of favicons (optional)',
    default: defaultValues.faviconBaseUrl,
    validate: function(v) {
      return (!v || v.match(/^http(s)?:\/\/\S+\/$/)) ? true : 'Please supply a valid url, starting with `http://` and ending with `/` - or leave field empty.';
    }
  },{
    type: 'checkbox',
    name: 'faviconSizes',
    message: 'What favicon sizes will be used?',
    default: defaultValues.faviconSizes,
    choices: [
      "96x96",
      "128x128",
      "144x144",
      "196x196",
      "256x256"
    ],
    when: function(answers) {
      return (answers.faviconBaseUrl);
    }
  },{
    type: 'input',
    name: 'ogImage',
    message: 'URL of standard teaser image (optional)',
    default: defaultValues.ogImage,
    validate: function(v) {
      return (!v || v.match(/^http(s)?:\/\/\S+$/)) ? true : 'Please supply a valid url, starting with `http://` or leave field empty.';
    },
    when: function(answers) {
      return (!answers.faviconBaseUrl);
    }
  },{
    type: 'input',
    name: 'twitterAccount',
    message: 'Twitter account name (optional)',
    default: defaultValues.twitterAccount,
    validate: function(v) {
      return (!v || v.match(/^[a-zA-z0-9_-]+$/)) ? true : 'Please supply a Twitter account name or leave field empty.';
    }
  },{
    type: 'input',
    name: 'themeColor',
    message: 'Basic color of your theme as hexcode (optional)',
    default: defaultValues.themeColor,
    validate: function(v) {
      return (!v || v.match(/^#[a-zA-z0-9]{3,6}$/)) ? true : 'Please supply a hex color code like `#fa647a`.';
    },
    filter: function(v) {
      return v.toLowerCase();
    }
  },{
    type: 'input',
    name: 'deployCmd',
    message: 'CLI command to copy files to your live server (optional)',
    default: defaultValues.deployCmd
  }
];

inquirer.prompt(questions).then(
  function (answers) {
    answers.theme = defaultValues.theme ? defaultValues.theme : themesAvailable[0];
    answers.defaultAuthor = {
      "email": answers.defaultAuthorEmail,
      "name": answers.defaultAuthor
    };
    delete answers.defaultAuthorEmail;
    answers.imageSizes = answers.imageSizes.map(function(i) {
      return i.split(/x/);
    });

    var ogImage = null;
    if (answers.faviconBaseUrl) {
      answers.icons = answers.faviconSizes.map(function(i) {
        ogImage = answers.faviconBaseUrl + 'favicon-'+i+'.png';
        return {
          src: ogImage,
          sizes: i,
        };
      });
    }
    if (!answers.ogImage && ogImage) {
      answers.ogImage = ogImage;
    }

    shell.mkdir('-p', defaultValues.directories.data);
    //console.log(answers);

    ['/css', '/js'].forEach(function(link) {
      fs.unlink(defaultValues.directories.htdocs + link, function() {
        fs.linkSync(defaultValues.directories.theme + '/' + answers.theme + link,defaultValues.directories.htdocs + link);
      });
    });
    fs.writeFile(configFilename, JSON.stringify(answers, undefined, 2), function(err) {
      if (err) {
        console.error(configFilename + ' could not be written' ); process.exit(1);
      } else {
        console.log( configFilename + ' created');
      }
    });
    fs.writeFile(defaultValues.directories.htdocs+'/robots.txt', "# http://www.robotstxt.org/\n\nUser-agent: *\nDisallow: /google*.html\n\nSitemap: "+defaultValues.baseUrl+defaultValues.basePath+"sitemap.xml\n", function(err) {
      if (err) {
        console.error('htdocs/robots.txt' + ' could not be written' ); process.exit(1);
      } else {
        console.log( 'htdocs/robots.txt' + ' created');
      }
    });
  },
  function(err) { console.error(err); process.exit(1); }
);
<|endoftext|>


<commit_before>var os = require('os');
var spawn = require('child_process').spawn;

var platform = os.platform();

console.log('bleno install: platform is "' + platform + "'");

var npmInstall = function(package, callback) {

};

if (platform === 'darwin') {
  console.log('bleno install: installing xpc-connection ...');

  var npmInstall = spawn('npm', ['install', 'xpc-connection@~0.1.0'], {
    stdio: 'inherit'
  });

  npmInstall.on('close', function(code) {
    console.log('bleno install: done');

    process.exit(code);
  });
} else if (platform === 'linux') {
  console.log('bleno install: running node-gyp ...');

  var nodeGypConfigureBuild = spawn('node-gyp', ['configure', 'build'], {
    stdio: 'inherit'
  });

  nodeGypConfigureBuild.on('close', function(code) {
    console.log('bleno install: done');

    process.exit(code);
  });
} else {
  console.error('bleno install: Your platform is not supported!');
  process.exit(-1);
}
<commit_msg>- node-gyp failure suggestion on Linux<commit_after>var os = require('os');
var spawn = require('child_process').spawn;

var platform = os.platform();

console.log('bleno install: platform is "' + platform + "'");

var npmInstall = function(package, callback) {

};

if (platform === 'darwin') {
  console.log('bleno install: installing xpc-connection ...');

  var npmInstall = spawn('npm', ['install', 'xpc-connection@~0.1.0'], {
    stdio: 'inherit'
  });

  npmInstall.on('close', function(code) {
    console.log('bleno install: done');

    process.exit(code);
  });
} else if (platform === 'linux') {
  console.log('bleno install: running node-gyp ...');

  var nodeGypConfigureBuild = spawn('node-gyp', ['configure', 'build'], {
    stdio: 'inherit'
  });

  nodeGypConfigureBuild.on('close', function(code) {
    console.log('bleno install: ' + ((code === 0) ? 'done' : 'error'));

    if (code !== 0) {
      console.error('Have you installed "libbluetooth-dev"? Try again, after running:');
      console.error();
      console.error('\t sudo apt-get install bluetooth bluez-utils libbluetooth-dev');
    }

    process.exit(code);
  });
} else {
  console.error('bleno install: Your platform is not supported!');
  process.exit(-1);
}
<|endoftext|>


<commit_before>var _ = require('lodash');

// Removes old monitoring data. We only want basic monitoring with the last 100 events.
// We keep last 80 and remove the rest to be sure.
function serverMonitoringCleanup(db, conn) {
    var exclude = {
        eventDate: 0,
        pid: 0,
        version: 0,
        uptime: 0,
        network: 0,
        connectionName: 0,
        connections: 0,
        memory: 0,
        dataRetrieved: 0,
        docCounts: 0
    }

    var retainedRecords = (24 * 60) * 60 / 30; // 24 hours worth of 30 sec blocks (data refresh interval)

    db.find({connectionName: conn}).skip(retainedRecords).sort({eventDate: -1}).projection(exclude).exec(function (err, serverEvents) {
        var idArray = [];
        _.each(serverEvents, function(value, key) {
            idArray.push(value._id);
        });

        db.remove({'_id':{'$in': idArray}}, { multi: true }, function (err, newDoc) {});
    });
};

// runs a regular job against the connections and inserts into a local DB
var currDocCounts = {
    queried: 0,
    inserted: 0,
    deleted: 0,
    updated: 0
}

exports.serverMonitoring = function (monitoringDB, dbs) {
    if(dbs){
        Object.keys(dbs).forEach(function(key) {
            var adminDb = dbs[key].native.admin();
            adminDb.serverStatus(function(err, info) {

                // if we got data back from db. If not, normally related to permissions
                var dataRetrieved = false;
                if(info){
                    dataRetrieved = true;
                }

                // doc numbers. We get the last interval number and subtract the current to get the diff
                var docCounts = getDocCounts(currDocCounts, info.metrics.document)

                var doc = {
                    eventDate: new Date(),
                    pid: info.pid,
                    version: info.version,
                    uptime: info.uptime,
                    activeClients: info.globalLock.activeClients,
                    connectionName: key,
                    connections: info.connections,
                    memory: info.mem,
                    dataRetrieved: dataRetrieved,
                    docCounts: docCounts
                }

                // insert the data into local DB
                monitoringDB.insert(doc, function (err, newDoc) {});

                // clean up old docs
                serverMonitoringCleanup(monitoringDB, key);
            });
        });
    }
}

function getDocCounts(currCounts, newCounts){
    var newDocCounts = {
        queried: 0,
        inserted: 0,
        deleted: 0,
        updated: 0
    }

    // queried
    if(currCounts.queried == 0){
        currCounts.queried = newCounts.returned;
    }else{
        newDocCounts.queried = newCounts.returned - currCounts.queried;
        currCounts.queried = newCounts.returned;
    }

    // inserts
    if(currCounts.inserted == 0){
        currCounts.inserted = newCounts.inserted;
    }else{
        newDocCounts.inserted = newCounts.inserted - currCounts.inserted;
        currCounts.inserted = newCounts.inserted;
    }

    // deleted
    if(currCounts.deleted == 0){
        currCounts.deleted = newCounts.deleted;
    }else{
        newDocCounts.deleted = newCounts.deleted - currCounts.deleted;
        currCounts.deleted = newCounts.deleted;
    }

    // updated
    if(currCounts.updated == 0){
        currCounts.updated = newCounts.updated;
    }else{
        newDocCounts.updated = newCounts.updated - currCounts.updated;
        currCounts.updated = newCounts.updated;
    }

    return newDocCounts;
}<commit_msg>Fix for issues monitoring connections which don't have admin access to DB<commit_after>var _ = require('lodash');

// Removes old monitoring data. We only want basic monitoring with the last 100 events.
// We keep last 80 and remove the rest to be sure.
function serverMonitoringCleanup(db, conn) {
    var exclude = {
        eventDate: 0,
        pid: 0,
        version: 0,
        uptime: 0,
        network: 0,
        connectionName: 0,
        connections: 0,
        memory: 0,
        dataRetrieved: 0,
        docCounts: 0
    }

    var retainedRecords = (24 * 60) * 60 / 30; // 24 hours worth of 30 sec blocks (data refresh interval)

    db.find({connectionName: conn}).skip(retainedRecords).sort({eventDate: -1}).projection(exclude).exec(function (err, serverEvents) {
        var idArray = [];
        _.each(serverEvents, function(value, key) {
            idArray.push(value._id);
        });

        db.remove({'_id':{'$in': idArray}}, { multi: true }, function (err, newDoc) {});
    });
};

// runs a regular job against the connections and inserts into a local DB
var currDocCounts = {
    queried: 0,
    inserted: 0,
    deleted: 0,
    updated: 0
}

exports.serverMonitoring = function (monitoringDB, dbs) {
    if(dbs){
        Object.keys(dbs).forEach(function(key) {
            var adminDb = dbs[key].native.admin();
            adminDb.serverStatus(function(err, info) {

                // if we got data back from db. If not, normally related to permissions
                var dataRetrieved = false;
                if(info){
                    dataRetrieved = true;
                }

                // doc numbers. We get the last interval number and subtract the current to get the diff
                var docCounts = "";
                var activeClients = "";
                var pid = "N/A";
                var version = "N/A";
                var uptime = "N/A";
                var connections = "";
                var memory = "";

                // set the values if we can get them
                if(info){
                    docCounts = getDocCounts(currDocCounts, info.metrics.document);
                    activeClients = info.globalLock.activeClients;
                    pid = info.pid;
                    version = info.version;
                    uptime = info.uptime;
                    connections= info.connections;
                    memory = info.mem;
                }

                var doc = {
                    eventDate: new Date(),
                    pid: pid,
                    version: version,
                    uptime: uptime,
                    activeClients: activeClients,
                    connectionName: key,
                    connections: connections,
                    memory: memory,
                    dataRetrieved: dataRetrieved,
                    docCounts: docCounts
                }

                // insert the data into local DB
                monitoringDB.insert(doc, function (err, newDoc) {});

                // clean up old docs
                serverMonitoringCleanup(monitoringDB, key);
            });
        });
    }
}

function getDocCounts(currCounts, newCounts){
    var newDocCounts = {
        queried: 0,
        inserted: 0,
        deleted: 0,
        updated: 0
    }

    // queried
    if(currCounts.queried == 0){
        currCounts.queried = newCounts.returned;
    }else{
        newDocCounts.queried = newCounts.returned - currCounts.queried;
        currCounts.queried = newCounts.returned;
    }

    // inserts
    if(currCounts.inserted == 0){
        currCounts.inserted = newCounts.inserted;
    }else{
        newDocCounts.inserted = newCounts.inserted - currCounts.inserted;
        currCounts.inserted = newCounts.inserted;
    }

    // deleted
    if(currCounts.deleted == 0){
        currCounts.deleted = newCounts.deleted;
    }else{
        newDocCounts.deleted = newCounts.deleted - currCounts.deleted;
        currCounts.deleted = newCounts.deleted;
    }

    // updated
    if(currCounts.updated == 0){
        currCounts.updated = newCounts.updated;
    }else{
        newDocCounts.updated = newCounts.updated - currCounts.updated;
        currCounts.updated = newCounts.updated;
    }

    return newDocCounts;
}<|endoftext|>


<commit_before>// Utilities for generating usable map representations from map tiles.
var mapParser = function() {}

// Takes in a tile grid and returns an array of shapes representing the
// grid. A shape is an array of vertices. A vertex is an objects with
// x and y properties corresponding to the location of the vertex.
mapParser.parse = function(tiles) {
  // Returns 1 if a cell is a bad cell, 0 otherwise.
  function isBadCell(elt) {
    var bad_cells = [0, 1, 7, 1.1, 1.2, 1.3, 1.4];
    if(bad_cells.indexOf(elt) !== -1) {
      return 1;
    } else {
      return 0;
    }
  }

  // Takes a 2D array and returns an array resulting from applying fn to
  // each value.
  function threshold(arr, fn) {
    return arr.map(function(row) {
      return row.map(fn);
    });
  }

  function map2d(arr, fn) {
    return arr.map(function(row) {
      return row.map(fn);
    });
  }

  // Given a rectangular 2D array, returns a 2D array with dimensions one
  // less in each direction where each cell is composed of the values of
  // the four surrounding it in the original array.
  function generateContourGrid(arr) {
    // Generate grid for holding values.
    var contour_grid = new Array(arr.length - 1);
    for (var n = 0; n < contour_grid.length; n++) {
      contour_grid[n] = new Array(arr[0].length - 1);
    }
    for (var i = 0; i < (arr.length - 1); i++) {
      for (var j = 0; j < (arr[0].length - 1); j++) {
        contour_grid[i][j] = [arr[i][j], arr[i][j+1], arr[i+1][j+1], arr[i+1][j]];
      }
    }
    return contour_grid;
  }

  // Return whether there should be a vertex at the given location and
  // which location to go next, if any.
  // Value returned is an object with property v and loc, v for whether
  // there is a vertex, and loc for the next location to move, if any.
  // loc is a string, of none, down, left, right, up, down corresponding to
  // tracing out a shape clockwise (or the interior of a shape CCW), or a function
  // that takes a string corresponding to the direction taken to get to the current
  // cell.
  // There will never be a vertex without a next direction.
  function getAction(cell) {
    var num = cell[0] * 8 + cell[1] * 4 + cell[2] * 2 + cell[3];
    switch(num) {
      case 0:
        return {v: false, loc: "none"};
      case 1:
        return {v: true, loc: "down"};
      case 2:
        return {v: true, loc: "right"};
      case 3:
        return {v: false, loc: "right"};
      case 4:
        return {v: true, loc: "up"};
      case 5:
        return {v: true, loc: function(prev_dir) {
          if (prev_dir == "right") {
            return "down";
          } else {
            return "up";
          }
        }};
      case 6:
        return {v: false, loc: "up"};
      case 7:
        return {v: true, loc: "up"};
      case 8:
        return {v: true, loc: "left"};
      case 9:
        return {v: false, loc: "down"};
      case 10:
        return {v: true, loc: function(prev_dir) {
          if (prev_dir == "down") {
            return "left";
          } else {
            return "right";
          }
        }};
      case 11:
        return {v: true, loc: "right"};
      case 12:
        return {v: false, loc: "left"};
      case 13:
        return {v: true, loc: "down"};
      case 14:
        return {v: true, loc: "left"};
      case 15:
        return {v: false, loc: "none"};
    }
  }

  // Returns the location of obj in arr with equality determined by cmp.
  // If no element is found then this returns -1.
  // cmp should be a function that takes two elements and returns true
  // if they are equal, false otherwise.
  function find(arr, obj, cmp) {
    if (typeof cmp !== 'undefined') {
      for (var i = 0; i < arr.length; i++) {
        if (cmp(arr[i], obj)) {
          return i;
        }
      }
      return -1;
    }
  }

  // Compare two array locations.
  function eltCompare(elt1, elt2) {
    return (elt1.c == elt2.c && elt1.r == elt2.r);
  }

  // Takes in the vertex/action information and returns an array of arrays,
  // where each array corresponds to a shape and each element of the array is
  // a vertex which is connected to it's previous and next neighbor (circular).
  function generateShapes(actionInfo) {
    // Total number of cells.
    var total = actionInfo.length * actionInfo[0].length;

    // Takes the current location and direction at this point and
    // returns the next location to check. Returns null if this cell is
    // not part of a shape.
    function nextNeighbor(elt, dir) {
      var drow = 0, dcol = 0;
      if (dir == "none") {
        return null;
      } else if (dir == "up") {
        drow = -1;
      } else if (dir == "down") {
        drow = 1;
      } else if (dir == "left") {
        dcol = -1;
      } else if (dir == "right") {
        dcol = 1;
      }
      return {r: elt.r + drow, c: elt.c + dcol};
    }

    // Get the next cell, from left to right, top to bottom. Returns null
    // if last element in array reached.
    function nextCell(elt) {
      if (elt.c + 1 < actionInfo[elt.r].length) {
        return {r: elt.r, c: elt.c + 1};
      } else if (elt.r + 1 < actionInfo.length) {
        return {r: elt.r + 1, c: 0};
      }
      return null;
    }

    var discovered = [];
    var node = {r: 0, c: 0};
    var shapes = [];
    var current_shape = [];
    var shape_node_start = null;
    var last_action = null;

    // Iterate until all nodes have been visited.
    while (discovered.length !== total) {
      if (!node) {
        console.log("Reached end.");
        break;
      }
      // It's okay to be in a discovered node if shapes are adjacent,
      // we just want to keep track of the ones we've seen.
      if (find(discovered, node, eltCompare) == -1) {
        discovered.push(node);
      }

      var action = actionInfo[node.r][node.c];
      var dir = action.loc;
      // And if this is the first element of the shape?
      if (typeof dir == 'function') {
        dir = dir(last_action);
      }
      last_action = dir;
      var next = nextNeighbor(node, dir);
      if (next) { // Part of a shape.
        // Save location for restarting after this shape has been defined.
        var first = false;
        if (current_shape.length == 0) {
          //console.log('setting');
          first = true;
          shape_node_start = node;
          shape_node_start_action = last_action;
        }

        // Current node and direction is same as at start of shape,
        // shape has been explored.
        if (!first && eltCompare(node, shape_node_start) && last_action == shape_node_start_action) {
          shapes.push(current_shape);
          current_shape = [];
          // Get the next undiscovered node.
          node = nextCell(shape_node_start);
          while (node && (find(discovered, node, eltCompare) !== -1)) {
            node = nextCell(node);
          }
          shape_node_start = null;
        } else {
          if (action.v || first) {
            current_shape.push(node);
          }
          node = next;
        }
      } else { // Not part of a shape.
        node = nextCell(node);
        // Get the next undiscovered node.
        while (node && (find(discovered, node, eltCompare) !== -1)) {
          node = nextCell(node);
        }
      }
    }
    return shapes;
  }

  // Takes in an array of shapes and converts from contour grid layout
  // to actual coordinates.
  function convertShapesToCoords(shapes) {
    var tile_width = 40;

    var new_shapes = map2d(shapes, function(loc) {
      return {x: (loc.r + 1) * tile_width, y: (loc.c + 1) * tile_width}
    });
    return new_shapes;
  }

  // Bring everything together.
  function doParse(tiles) {
    // Actually doing the conversion.
    // Generate threshold for map.
    var threshold_tiles = threshold(tiles, isBadCell);

    // Generate contour grid.
    var contour_grid_2 = generateContourGrid(threshold_tiles);

    // Get tile vertex and actions for each cell in contour grid.
    var tile_actions = threshold(contour_grid_2, getAction);

    var generated_shapes = generateShapes(tile_actions);
    var actual_shapes = generated_shapes.filter(function(elt) {
      return elt.length > 0;
    });

    var converted_shapes = convertShapesToCoords(actual_shapes);
    return converted_shapes;
  }

  return doParse(tiles);
}

// Drawing functions.
// Takes in an array of x, y objects
function drawShape(shapeInfo, canvas) {
  canvas.beginPath();
  var start = shapeInfo.shift();
  canvas.moveTo(start.x, start.y);
  for (var i = 0; i < shapeInfo.length; i++) {
    canvas.lineTo(shapeInfo[i].x, shapeInfo[i].y);
  }
  canvas.lineTo(start.x, start.y);
  canvas.lineWidth = 1;
  canvas.strokeStyle = 'black';
  canvas.stroke();
  canvas.closePath();
}

// Takes in a polygon
function drawPoly(poly, canvas, color) {
  if (typeof color == 'undefined') color = 'black';
  canvas.beginPath();
  var start = poly.getPoint(0);
  canvas.moveTo(start.x, start.y);
  for (var i = 1; i < poly.numpoints; i++) {
    canvas.lineTo(poly.getPoint(i).x, poly.getPoint(i).y);
  }
  canvas.lineTo(start.x, start.y);
  canvas.lineWidth = 1;
  canvas.strokeStyle = color;
  canvas.stroke();
  canvas.closePath();
}

function initCanvas() {
  var c = document.getElementById('c');
  c.width = tiles.length * 40;
  c.height = tiles[0].length * 40;
  var c2 = c.getContext('2d');
  c2.fillStyle = '#d00';
  return c2;
}

// Draw outlines on canvas.
function drawOutline(shapes, c2) {
  for (var i = 0; i < shapes.length; i++) {
    if (shapes[i] instanceof Poly) {
      drawPoly(shapes[i], c2);
    } else {
      drawShape(shapes[i], c2);
    }
  }
}

// Convert arrays of points into Polys.
function convertArraysToPolys(shapes) {
  var polys = shapes.map(function(shape) {
    var poly = new Poly();
    poly.init(shape.length);
    for (var i = 0; i < shape.length; i++) {
      var point = new Point(shape[i].x, shape[i].y);
      poly.setPoint(i, point);
    }
    return poly;
  });
  return polys;
}

// Try to generate navigation mesh using shapes.
function getNavMesh(polys) {
  // Get main map outline by checking for the polygon with the largest
  // area.
  var best_poly = polys[0];
  var best_poly_index = 0;
  var best_poly_area = Math.abs(polys[0].getArea());
  console.log(polys[0].getArea());
  for (var i = 1; i < polys.length; i++) {
    if (Math.abs(polys[i].getArea()) > best_poly_area) {
      best_poly = polys[i];
      best_poly_index = i;
      best_poly_area = Math.abs(polys[i].getArea());
    }
  }

  // Remove outline polygon.
  polys.splice(best_poly_index, 1);

  // Set the rest of the elements as holes.
  polys.forEach(function(e) {
    e.setOrientation("CW");
    e.hole = true;
  });

  // Add outline polygon back in.
  polys.unshift(best_poly);

  var partitioner = new Partition();

  // Remove holes from poly.
  //var with_holes_removed = partitioner.removeHoles(polys);

  // Get polygons defining regions of map.
  //var parts = partitioner.convexPartition(with_holes_removed);
  best_poly.subdivide(240);
  var parts = partitioner.convexPartition(best_poly);
  return parts;
}

var tiles = tile_grids["SNESv2"];
// Get outline of walls in map.
var shapeArrays = mapParser.parse(tiles);
var c2d = initCanvas();
//drawOutline(shapeArrays, c2d);

var polys = convertArraysToPolys(shapeArrays);
var parts = getNavMesh(polys);
//console.log(fullparts.length + " parts generated.");
drawOutline(parts, c2d);

<commit_msg>Pass single polygon to convexPartition instead of array.<commit_after>// Utilities for generating usable map representations from map tiles.
var mapParser = function() {}

// Takes in a tile grid and returns an array of shapes representing the
// grid. A shape is an array of vertices. A vertex is an objects with
// x and y properties corresponding to the location of the vertex.
mapParser.parse = function(tiles) {
  // Returns 1 if a cell is a bad cell, 0 otherwise.
  function isBadCell(elt) {
    var bad_cells = [0, 1, 7, 1.1, 1.2, 1.3, 1.4];
    if(bad_cells.indexOf(elt) !== -1) {
      return 1;
    } else {
      return 0;
    }
  }

  // Takes a 2D array and returns an array resulting from applying fn to
  // each value.
  function threshold(arr, fn) {
    return arr.map(function(row) {
      return row.map(fn);
    });
  }

  function map2d(arr, fn) {
    return arr.map(function(row) {
      return row.map(fn);
    });
  }

  // Given a rectangular 2D array, returns a 2D array with dimensions one
  // less in each direction where each cell is composed of the values of
  // the four surrounding it in the original array.
  function generateContourGrid(arr) {
    // Generate grid for holding values.
    var contour_grid = new Array(arr.length - 1);
    for (var n = 0; n < contour_grid.length; n++) {
      contour_grid[n] = new Array(arr[0].length - 1);
    }
    for (var i = 0; i < (arr.length - 1); i++) {
      for (var j = 0; j < (arr[0].length - 1); j++) {
        contour_grid[i][j] = [arr[i][j], arr[i][j+1], arr[i+1][j+1], arr[i+1][j]];
      }
    }
    return contour_grid;
  }

  // Return whether there should be a vertex at the given location and
  // which location to go next, if any.
  // Value returned is an object with property v and loc, v for whether
  // there is a vertex, and loc for the next location to move, if any.
  // loc is a string, of none, down, left, right, up, down corresponding to
  // tracing out a shape clockwise (or the interior of a shape CCW), or a function
  // that takes a string corresponding to the direction taken to get to the current
  // cell.
  // There will never be a vertex without a next direction.
  function getAction(cell) {
    var num = cell[0] * 8 + cell[1] * 4 + cell[2] * 2 + cell[3];
    switch(num) {
      case 0:
        return {v: false, loc: "none"};
      case 1:
        return {v: true, loc: "down"};
      case 2:
        return {v: true, loc: "right"};
      case 3:
        return {v: false, loc: "right"};
      case 4:
        return {v: true, loc: "up"};
      case 5:
        return {v: true, loc: function(prev_dir) {
          if (prev_dir == "right") {
            return "down";
          } else {
            return "up";
          }
        }};
      case 6:
        return {v: false, loc: "up"};
      case 7:
        return {v: true, loc: "up"};
      case 8:
        return {v: true, loc: "left"};
      case 9:
        return {v: false, loc: "down"};
      case 10:
        return {v: true, loc: function(prev_dir) {
          if (prev_dir == "down") {
            return "left";
          } else {
            return "right";
          }
        }};
      case 11:
        return {v: true, loc: "right"};
      case 12:
        return {v: false, loc: "left"};
      case 13:
        return {v: true, loc: "down"};
      case 14:
        return {v: true, loc: "left"};
      case 15:
        return {v: false, loc: "none"};
    }
  }

  // Returns the location of obj in arr with equality determined by cmp.
  // If no element is found then this returns -1.
  // cmp should be a function that takes two elements and returns true
  // if they are equal, false otherwise.
  function find(arr, obj, cmp) {
    if (typeof cmp !== 'undefined') {
      for (var i = 0; i < arr.length; i++) {
        if (cmp(arr[i], obj)) {
          return i;
        }
      }
      return -1;
    }
  }

  // Compare two array locations.
  function eltCompare(elt1, elt2) {
    return (elt1.c == elt2.c && elt1.r == elt2.r);
  }

  // Takes in the vertex/action information and returns an array of arrays,
  // where each array corresponds to a shape and each element of the array is
  // a vertex which is connected to it's previous and next neighbor (circular).
  function generateShapes(actionInfo) {
    // Total number of cells.
    var total = actionInfo.length * actionInfo[0].length;

    // Takes the current location and direction at this point and
    // returns the next location to check. Returns null if this cell is
    // not part of a shape.
    function nextNeighbor(elt, dir) {
      var drow = 0, dcol = 0;
      if (dir == "none") {
        return null;
      } else if (dir == "up") {
        drow = -1;
      } else if (dir == "down") {
        drow = 1;
      } else if (dir == "left") {
        dcol = -1;
      } else if (dir == "right") {
        dcol = 1;
      }
      return {r: elt.r + drow, c: elt.c + dcol};
    }

    // Get the next cell, from left to right, top to bottom. Returns null
    // if last element in array reached.
    function nextCell(elt) {
      if (elt.c + 1 < actionInfo[elt.r].length) {
        return {r: elt.r, c: elt.c + 1};
      } else if (elt.r + 1 < actionInfo.length) {
        return {r: elt.r + 1, c: 0};
      }
      return null;
    }

    var discovered = [];
    var node = {r: 0, c: 0};
    var shapes = [];
    var current_shape = [];
    var shape_node_start = null;
    var last_action = null;

    // Iterate until all nodes have been visited.
    while (discovered.length !== total) {
      if (!node) {
        console.log("Reached end.");
        break;
      }
      // It's okay to be in a discovered node if shapes are adjacent,
      // we just want to keep track of the ones we've seen.
      if (find(discovered, node, eltCompare) == -1) {
        discovered.push(node);
      }

      var action = actionInfo[node.r][node.c];
      var dir = action.loc;
      // And if this is the first element of the shape?
      if (typeof dir == 'function') {
        dir = dir(last_action);
      }
      last_action = dir;
      var next = nextNeighbor(node, dir);
      if (next) { // Part of a shape.
        // Save location for restarting after this shape has been defined.
        var first = false;
        if (current_shape.length == 0) {
          //console.log('setting');
          first = true;
          shape_node_start = node;
          shape_node_start_action = last_action;
        }

        // Current node and direction is same as at start of shape,
        // shape has been explored.
        if (!first && eltCompare(node, shape_node_start) && last_action == shape_node_start_action) {
          shapes.push(current_shape);
          current_shape = [];
          // Get the next undiscovered node.
          node = nextCell(shape_node_start);
          while (node && (find(discovered, node, eltCompare) !== -1)) {
            node = nextCell(node);
          }
          shape_node_start = null;
        } else {
          if (action.v || first) {
            current_shape.push(node);
          }
          node = next;
        }
      } else { // Not part of a shape.
        node = nextCell(node);
        // Get the next undiscovered node.
        while (node && (find(discovered, node, eltCompare) !== -1)) {
          node = nextCell(node);
        }
      }
    }
    return shapes;
  }

  // Takes in an array of shapes and converts from contour grid layout
  // to actual coordinates.
  function convertShapesToCoords(shapes) {
    var tile_width = 40;

    var new_shapes = map2d(shapes, function(loc) {
      return {x: (loc.r + 1) * tile_width, y: (loc.c + 1) * tile_width}
    });
    return new_shapes;
  }

  // Bring everything together.
  function doParse(tiles) {
    // Actually doing the conversion.
    // Generate threshold for map.
    var threshold_tiles = threshold(tiles, isBadCell);

    // Generate contour grid.
    var contour_grid_2 = generateContourGrid(threshold_tiles);

    // Get tile vertex and actions for each cell in contour grid.
    var tile_actions = threshold(contour_grid_2, getAction);

    var generated_shapes = generateShapes(tile_actions);
    var actual_shapes = generated_shapes.filter(function(elt) {
      return elt.length > 0;
    });

    var converted_shapes = convertShapesToCoords(actual_shapes);
    return converted_shapes;
  }

  return doParse(tiles);
}

// Drawing functions.
// Takes in an array of x, y objects
function drawShape(shapeInfo, canvas) {
  canvas.beginPath();
  var start = shapeInfo.shift();
  canvas.moveTo(start.x, start.y);
  for (var i = 0; i < shapeInfo.length; i++) {
    canvas.lineTo(shapeInfo[i].x, shapeInfo[i].y);
  }
  canvas.lineTo(start.x, start.y);
  canvas.lineWidth = 1;
  canvas.strokeStyle = 'black';
  canvas.stroke();
  canvas.closePath();
}

// Takes in a polygon
function drawPoly(poly, canvas, color) {
  if (typeof color == 'undefined') color = 'black';
  canvas.beginPath();
  var start = poly.getPoint(0);
  canvas.moveTo(start.x, start.y);
  for (var i = 1; i < poly.numpoints; i++) {
    canvas.lineTo(poly.getPoint(i).x, poly.getPoint(i).y);
  }
  canvas.lineTo(start.x, start.y);
  canvas.lineWidth = 1;
  canvas.strokeStyle = color;
  canvas.stroke();
  canvas.closePath();
}

function initCanvas() {
  var c = document.getElementById('c');
  c.width = tiles.length * 40;
  c.height = tiles[0].length * 40;
  var c2 = c.getContext('2d');
  c2.fillStyle = '#d00';
  return c2;
}

// Draw outlines on canvas.
function drawOutline(shapes, c2) {
  for (var i = 0; i < shapes.length; i++) {
    if (shapes[i] instanceof Poly) {
      drawPoly(shapes[i], c2);
    } else {
      drawShape(shapes[i], c2);
    }
  }
}

// Convert arrays of points into Polys.
function convertArraysToPolys(shapes) {
  var polys = shapes.map(function(shape) {
    var poly = new Poly();
    poly.init(shape.length);
    for (var i = 0; i < shape.length; i++) {
      var point = new Point(shape[i].x, shape[i].y);
      poly.setPoint(i, point);
    }
    return poly;
  });
  return polys;
}

// Try to generate navigation mesh using shapes.
function getNavMesh(polys) {
  // Get main map outline by checking for the polygon with the largest
  // area.
  var best_poly = polys[0];
  var best_poly_index = 0;
  var best_poly_area = Math.abs(polys[0].getArea());
  console.log(polys[0].getArea());
  for (var i = 1; i < polys.length; i++) {
    if (Math.abs(polys[i].getArea()) > best_poly_area) {
      best_poly = polys[i];
      best_poly_index = i;
      best_poly_area = Math.abs(polys[i].getArea());
    }
  }

  // Remove outline polygon.
  polys.splice(best_poly_index, 1);

  // Set the rest of the elements as holes.
  polys.forEach(function(e) {
    e.setOrientation("CW");
    e.hole = true;
  });

  // Add outline polygon back in.
  polys.unshift(best_poly);

  var partitioner = new Partition();

  // Remove holes from poly.

  // Get polygons defining regions of map.
  //best_poly.subdivide(240);
  var with_holes_removed = partitioner.removeHoles(polys);
  var parts = partitioner.convexPartition(with_holes_removed[0]);
  //var parts = partitioner.convexPartition(with_holes_removed);
  return parts;
}

var tiles = tile_grids["SNESv2"];
// Get outline of walls in map.
var shapeArrays = mapParser.parse(tiles);
var c2d = initCanvas();
//drawOutline(shapeArrays, c2d);

var polys = convertArraysToPolys(shapeArrays);
var parts = getNavMesh(polys);
//console.log(fullparts.length + " parts generated.");
drawOutline(parts, c2d);

<|endoftext|>


<commit_before>import React from 'react';

class Headline extends React.Component {
  render() {
    const style = {
      width: '40%',
      marginLeft: '60%',
      clear: 'both',
      float: 'left',
      color: 'white'
    };

    return (

Educate a child

The gift of education can break the cycle of poverty and prevent child labour.

    );
  }
}

export default Headline;
<commit_msg>Shift Headline near child's eyes<commit_after>import React from 'react';

class Headline extends React.Component {
  render() {
    const style = {
      width: '40%',
      marginLeft: '60%',
      marginTop: '250px',
      clear: 'both',
      float: 'left',
      color: 'white'
    };

    return (

Educate a child

The gift of education can break the cycle of poverty and prevent child labour.

    );
  }
}

export default Headline;
<|endoftext|>