/*! was.js - v1.0.4 - 2019-08-03 
* http://grimore.org
* Copyright (c) 2019 [object Object]; Licensed GPL-3.0 */
/*    Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3    */
/*************************************************************************/
function wasProduct(a, b) {
    var m = Math.max(a.length, b.length);
    var o = {};
    for(var i = 0; i < m; ++i) {
        o[a[i]] = b[i];
    }
    return o;
}
if (!Array.prototype.product) {
    Array.prototype.product = function(b) {
        return wasProduct(this, b);
    };
}
// jQuery
if(typeof jQuery === 'function') {
    $.extend({
        product: wasProduct
    });
}

/*************************************************************************/
/*    Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3    */
/*************************************************************************/
function wasStride(a, s) {
    return a.filter(function(e, i) {
        return i % s === 0;
    });
}
if (!Array.prototype.stride) {
    Array.prototype.stride = function(s) {
        return wasStride(this, s);
    };
}
// jQuery
if(typeof jQuery === 'function') {
    $.extend({
        stride: wasStride
    });
}

/*************************************************************************/
/*    Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3    */
/*************************************************************************/
// Vanilla JavaScript
function wasChunk(a, n) {
    if (!a.length) {
        return [];
    }
    return [a.slice(0, n)]
        .concat(a.slice(n).wasChunk(n));
}
if (!Array.prototype.chunk) {
    Array.prototype.chunk = function(a, n) {
        return wasChunk(this, n);
    };
}
// jQuery
if(typeof jQuery === 'function') {
    $.extend({
        chunk: wasChunk
    });
}

/*************************************************************************/
/*    Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3    */
/*************************************************************************/
/*stackoverflow.com/questions/7837456/how-to-compare-arrays-in-javascript*/
/*************************************************************************/
// Vanilla JavaScript
function wasEquals(a, b) {
    // if the other array is a falsy value, return
    if (!b) {
        return false;
    }

    // compare lengths - can save a lot of time 
    if (a.length !== b.length) {
        return false;
    }

    for (var i = 0, l = a.length; i < l; i++) {
        // Check if we have nested arrays
        if (a[i] instanceof Array && b[i] instanceof Array) {
            // recurse into the nested arrays
            if (!a[i].equals(b[i])) {
                return false;
            }
        } else if (a[i] !== b[i]) {
            // Warning - two different object instances will never be equal: {x:20} != {x:20}
            return false;
        }
    }
    return true;
}
if (!Array.prototype.equals) {
    // attach the .equals method to Array's prototype to call it on any array
    Array.prototype.equals = function(a, b) {
        return wasEquals(this, b);
    };
}
// jQuery
if(typeof jQuery === 'function') {
    $.extend({
        equals: wasEquals
    });
}

/*************************************************************************/
/* Node.JS package export.                                               */
/*************************************************************************/
if(typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
    module.exports.collections = {
        product: wasProduct,
        stride: wasStride,
        chunk: wasChunk,
        equals: wasEquals
    };
}

/*    Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3    */
/*************************************************************************/
function wasCSVToArray(csv) {
    var l = [];
    var s = [];
    var m = "";
 
    do {
        var a = csv.charAt(0);
        csv = csv.slice(1, csv.length);
        if(a === ",") {
            if(s[s.length-1] !== '"') {
                l.push(m);
                m = "";
                continue;
            }
            m += a;
            continue;
        }
        if(a === '"' && csv.charAt(0) === a) {
            m += a;
            csv = csv.slice(1, csv.length);
            continue;
        }
        if(a === '"') {
            if(s[s.length-1] !== a) {
                s.push(a);
                continue;
            }
            s.pop();
            continue;
        }
        m += a;
    } while(csv !== "");
 
    l.push(m);
 
    return l;
}

/*************************************************************************/
/*    Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3    */
/*************************************************************************/
function wasArrayToCSV(a) {
    var csv = [];
    for(var i=0; i<a.length; ++i) {
        var cell = a[i].toString().replace('"', '""');
        if(/"\s,\r\n/.test(cell)) {
            csv[i] = '"' + cell + '"';
            continue;
        }
        csv[i] = cell;
    }
    return csv.join();
}

/* Node.JS package export.                                               */
/*************************************************************************/
if(typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
    /* global wasCSVToArray, wasArrayToCSV, wasKeyValueToObject */
    module.exports.formats = {
        csv: {
            CSVToArray: wasCSVToArray,
            ArrayToCSV: wasArrayToCSV
        },
        kvp: {
            KeyValueToObject: wasKeyValueToObject
        }
    };
}

/*    Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3    */
/*************************************************************************/
function wasKeyValueToObject(a) {
    var o = {};
    a.reduce(function(a, c, i) {
        i = Math.floor(i / 2);
        if (!a[i]) {
            a[i] = [];
        }
        a[i].push(c);
        return a;
    }, []).forEach(function(c, i, a) {
        o[c[0]] = c[1];
    }, o);
    return o;
}

/*    Copyright (C) 2017 Wizardry and Steamworks - License: GNU GPLv3    */
/*************************************************************************/
/* fuss/lambda_calculus/functional_programming/aggregators @ grimore.org */
/*************************************************************************/
function wasSwitch() {
    if(arguments.length % 2 !== 0) {
        throw "Pairs of predicates expected for cases";
    }
    
    (Array.isArray(arguments[0]) ? arguments[0] : [ arguments[0] ]).forEach(function(s) {
        var m = false;
        for(var i = 2; i < arguments.length; i += 2) {
            if(!arguments[i](s)) {
                continue;
            }
            if(!arguments[i + 1](s)) {
                continue;
            }
            m = true;
        }
    
        if(!m) {
            arguments[1](s);
        }
    });
}
if (!Array.prototype.switch) {
    Array.prototype.switch = function() {
        wasSwitch(this, arguments[0], arguments.slice(1));
    };
}
// jQuery
if(typeof jQuery === 'function') {
    $.extend({
        switch: wasSwitch
    });
}

/*************************************************************************/
/* Node.JS package export.                                               */
/*************************************************************************/
if(typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
    module.exports.lambda = {
        switch: wasSwitch
    };
}

/*    Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3    */
/*************************************************************************/
function wasMapValueToRange(value, xMin, xMax, yMin, yMax) {
    return yMin + (
        ( yMax - yMin ) * ( value - xMin ) / ( xMax - xMin )
    );
}

/*************************************************************************/
/* Node.JS package export.                                               */
/*************************************************************************/
if(typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
    module.exports.mathematics = {
        MapValueToRange: wasMapValueToRange
    };
}

/*    Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3    */
/*************************************************************************/
function wasHexToRGB(hex) {
    var shortRegEx = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
    hex = hex.replace(
        shortRegEx,
        function(m, r, g, b) {
            return r + r + g + g + b + b;
        }
    );

    var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
    return result ? {
        r: parseInt(result[1], 16),
        g: parseInt(result[2], 16),
        b: parseInt(result[3], 16)
    } : null;
}

/*************************************************************************/
/*    Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3    */
/*************************************************************************/
function wasRGBToHex(r, g, b) {
    return "#" + (
        (1 << 24) +
        (r << 16) +
        (g << 8) +
        b
    ).toString(16).slice(1);
}

/*************************************************************************/
/* Node.JS package export.                                               */
/*************************************************************************/
if(typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
    module.exports.physics = {
        HexToRGB: wasHexToRGB,
        RGBToHex: wasRGBToHex
    };
}
