<commit_before>(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD. Register as an anonymous module.
        define(function () {
            return (root.Fiji = factory());
        });
    } else if (typeof exports === 'object') {
        // Node.js
        module.exports = root.Fiji = factory();
    } else {
        // Browser globals
        root.Fiji = factory();
    }
}(this, function() {
    "use strict";

    var locSto = window.localStorage;
    var sesSto = window.sessionStorage;

    var DEFAULT_TTL = 1000*60*60*24;
    var DEFAULT_LONG_TTL = 1000*60*60*24*30;
    var DEFAULT_NS = 'Fiji';
    var DEFAULT_DEBUG = false;

    /**
     * Creates a new Fiji object
     * @class Fiji
     * @param {Object} [options]
     */
    var Fiji = function Fiji(options) {
        // Ensure this was called with the 'new' keyword
        if (!(this instanceof Fiji)) {
            return new Fiji(options);
        }

        /** @private {Object} */
        var _options = Object.create(null, {
            ttl:     { value: (options && options.ttl) ?
                              options.ttl : DEFAULT_TTL },
            longTtl: { value: (options && options.longTtl) ?
                              options.longTtl : DEFAULT_LONG_TTL },
            ns:      { value: (options && options.ns) ?
                              options.ns : DEFAULT_NS },
            debug:   { value: options ? !!options.debug : DEFAULT_DEBUG }
        });

        /** @private {Object} */
        var _cache = {};

        if (_options.debug) {
            console.log('Cleaning localStorage and sessionStorage (for testing only)');
            locSto.removeItem(_options.ns);
            sesSto.removeItem(_options.ns);
        }

        /**
        * Validate a well-formed cache/storage object (used internally).
        * @private
        * @param {Object} item
        * @returns {Boolean}
        */
        var validateItem = function validateItem(item) {
            return (item &&
                    item.hasOwnProperty('id') &&
                    item.hasOwnProperty('value') &&
                    item.hasOwnProperty('expires') &&
                    item.hasOwnProperty('isLongTerm') &&
            typeof item.id         !== 'undefined' &&
            typeof item.value      !== 'undefined' &&
            typeof item.expires    !== 'undefined' &&
            typeof item.isLongTerm !== 'undefined')
        };

        /**
        * Add a TTL value to a date and return a new date to use as expiry value.
        * @private
        * @param {Number} [ttl]
        * @param {Date} [now]
        * @returns {Date}
        */
        var calculateExpiresDate = function calculateExpiresDate(ttl, now) {
            var _now = (typeof now === 'object' && now.toDateString) ? now : new Date();
            var _ttl = ttl || _options.ttl;
            return new Date(_now.valueOf() + _ttl);
        };

        /**
        * Create a new well-formed cache/storage object (used internally).
        * @private
        * @param {String} key
        * @param {*} value
        * @param {Boolean} [isLongTerm]
        * @returns {Object}
        */
        var createNewItem = function createNewItem(key, value, isLongTerm) {
            var _value = (typeof value === 'undefined') ? null : value;
            var _isLongTerm = !!isLongTerm;
            return {
                id: key,
                value: _value,
                expires: calculateExpiresDate((isLongTerm ? _options.ttl : _options.longTtl)),
                isLongTerm: _isLongTerm
            };
        };

        /**
        * @private
        * @param {String} key
        * @returns {Object}
        */
        var getCacheItem = function getCacheItem(key) {
            if (!key) {
                if (_options.debug) console.warn('Please provide a key');
                return;
            }

            var item = _cache[key];
            return validateItem(item) ? item : null;
        };

        /**
        * @private
        * @param {Object} item
        */
        var setCacheItem = function setCacheItem(item) {
            if (!validateItem(item)) {
                if (_options.debug) console.warn('Item was not set or properly formed: ', item);
                return;
            }

            _cache[item.id] = item;
        };

        /**
        * @private
        * @param {String} key
        */
        var deleteCacheItem = function deleteCacheItem(key) {
            if (!key) {
                if (_options.debug) console.warn('Please provide a key');
                return;
            }

            if (typeof _cache[key] !== 'undefined') {
                _cache[key] = null;
                delete _cache[key];
            }
        };

        /**
        * @private
        * @param {String} key
        * @returns {Object}
        */
        var getStoreItem = function getStoreItem(key) {
            if (!key) {
                if (_options.debug) console.warn('Please provide a key');
                return;
            }

            var item = _cache[key];

            // default to session storage
            var storeMechanism = (validateItem(item) && item.isLongTerm) ? locSto : sesSto;
            var storeObj = JSON.parse(storeMechanism.getItem(_options.ns));

            if (!storeObj) {
                return null;
            }

            item = (typeof storeObj[key] === 'undefined') ? null : storeObj[key];

            return item;
        };

        /**
        * @private
        * @param {Object} item
        */
        var setStoreItem = function setStoreItem(item) {
            if (!validateItem(item)) {
                if (_options.debug) console.warn('Item was not set or properly formed: ', item);
                return;
            }

            var storeMechanism = item.isLongTerm ? locSto : sesSto;
            var storeObj = JSON.parse(storeMechanism.getItem(_options.ns));

            if (!storeObj) {
                storeObj = {};
            }
            storeObj[item.id] = item;

            storeMechanism.setItem(_options.ns, JSON.stringify(storeObj));
        };

        /**
        * @private
        * @param {String} key
        */
        var deleteStoreItem = function deleteStoreItem(key) {
            if (!key) {
                if (_options.debug) console.warn('Please provide a key');
                return;
            }

            var item = _cache[key];

            if (!validateItem(item)) {
                if (_options.debug) console.warn('Item was not set or properly formed: ', item);
                return;
            }

            var storeMechanism = item.isLongTerm ? locSto : sesSto;
            var storeObj = JSON.parse(storeMechanism.getItem(_options.ns));

            storeObj[item.id] = null;
            delete storeObj[item.id];

            storeMechanism.setItem(_options.ns, JSON.stringify(storeObj));
        };

        /**
        * @private
        * @param {Object} item
        * @returns {Boolean}
        */
        var isExpired = function isExpired(item) {
            if (!item) {
                if (_options.debug) console.warn('Please provide an item');
                return;
            }

            var now = new Date();

            return new Date(item.expires.valueOf()) < now;
        };

        /**
        * @method
        * @param {String} key
        * @returns {*}
        */
        this.get = function get(key) {
            var now = new Date();
            var storeObj;
            var item = getCacheItem(key);

            if (!item) {

                // prime cache
                storeObj = getStoreItem(key);
                if (!storeObj) {
                    storeObj = createNewItem(key, null);
                }
                setCacheItem(storeObj);
                item = getCacheItem(key);

                if (_options.debug) {
                    console.log('Initialized new cache item because blank "' + key + '"');
                    console.table(_cache);
                }

            } else if (isExpired(item)) {

                // refresh expired cached item from storage
                storeObj = getStoreItem(key);
                if (validateItem(storeObj)) {
                    item.value = storeObj.value;
                }
                item.expires = calculateExpiresDate((item.isLongTerm ? _options.ttl : _options.longTtl));
                setStoreItem(item);
                setCacheItem(item);

                if (_options.debug) {
                    console.log('Updated cache item because expired "' + key + '" (' + item.value + ')');
                    console.table(_cache);
                }

            } else {

                if (_options.debug) {
                    console.log('No cache init or update required, our data is still fresh.');
                    console.table(_cache);
                }

            }

            if (_options.debug) console.log('It is now ' + now.toString() + ' and _cache[' + key + '] expires at ', item.expires.toString());

            return item.value;
        };

        /**
        * @method
        * @param {String} key
        * @param {*} value
        * @param {Boolean} [isLongTerm]
        */
        this.set = function set(key, value, isLongTerm) {
            var now = new Date();
            var item = getCacheItem(key);

            if (!item) {

                item = createNewItem(key, value, isLongTerm);
                if (_options.debug) {
                    console.log('Initialized new cache item because blank "' + key + '"');
                    console.table(_cache);
                }

            } else {

                item.value = value;
                item.expires = calculateExpiresDate((item.isLongTerm ? _options.ttl : _options.longTtl));
                if (_options.debug) {
                    console.log('Updated existing cache item "' + key + '" (' + value + ') : ' + now.toString());
                    console.table(_cache);
                }

            }

            // Ensure we never save the same key to two different types of storage.
            // If a different isLongTerm option is passed, delete the existing storage item.
            if (item.isLongTerm !== !!isLongTerm) {
                deleteStoreItem(key);
                item.isLongTerm = isLongTerm;
            }

            setStoreItem(item);
            setCacheItem(item);
        };

        /**
        * @method
        * @param {String} key
        * @param {Boolean} [confirmDeleteAll]
        */
        this.del = function del(key, confirmDeleteAll) {
            // Provide the means to wipe the whole slate clean if desired.
            if (!key && confirmDeleteAll) {
                sesSto.removeItem(_options.ns);
                locSto.removeItem(_options.ns);
                _cache = null;
                _cache = {};
                if (_options.debug) console.log('Nuked the Fiji, kaboom!');
                return;
            }

            // Important to delete store item first so that the storage mechanism, if any, can be determined
            deleteStoreItem(key)
            deleteCacheItem(key)
        };

        /**
        * @method
        */
        this.list = function list() {
            var valuesObj = {};
            var keys = Object.keys(_cache);
            for (var i = 0; i < keys.length; i++) {
                valuesObj[keys[i]] = this.get(keys[i]);
            }
            return valuesObj;
        };

    };

    return Fiji;

}));
<commit_msg>Fix up jsdoc annotations<commit_after>(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD. Register as an anonymous module.
        define(function () {
            return (root.Fiji = factory());
        });
    } else if (typeof exports === 'object') {
        // Node.js
        module.exports = root.Fiji = factory();
    } else {
        // Browser globals
        root.Fiji = factory();
    }
}(this, function() {
    "use strict";

    var locSto = window.localStorage;
    var sesSto = window.sessionStorage;

    var DEFAULT_TTL = 1000*60*60*24;
    var DEFAULT_LONG_TTL = 1000*60*60*24*30;
    var DEFAULT_NS = 'Fiji';
    var DEFAULT_DEBUG = false;

    /**
     * Creates a new Fiji object
     * @class Fiji
     * @param {Object} [options]
     */
    var Fiji = function Fiji(options) {
        // Ensure this was called with the 'new' keyword
        if (!(this instanceof Fiji)) {
            return new Fiji(options);
        }

        /** @private {Object} */
        var _options = Object.create(null, {
            ttl:     { value: (options && typeof options.ttl !== 'undefined') ?
                              options.ttl : DEFAULT_TTL },
            longTtl: { value: (options && typeof options.longTtl !== 'undefined') ?
                              options.longTtl : DEFAULT_LONG_TTL },
            ns:      { value: (options && typeof options.ns !== 'undefined') ?
                              options.ns : DEFAULT_NS },
            debug:   { value: (options && typeof options.debug !== 'undefined') ?
                              !!options.debug : DEFAULT_DEBUG }
        });

        /** @private {Object} */
        var _cache = {};

        if (_options.debug) {
            console.log('Cleaning localStorage and sessionStorage (for testing only)');
            locSto.removeItem(_options.ns);
            sesSto.removeItem(_options.ns);
        }

        /**
         * Validate a well-formed cache/storage object (used internally).
         * @private
         * @param {Object} item
         * @returns {Boolean}
         */
        var validateItem = function validateItem(item) {
            return (item &&
                    item.hasOwnProperty('id') &&
                    item.hasOwnProperty('value') &&
                    item.hasOwnProperty('expires') &&
                    item.hasOwnProperty('isLongTerm') &&
            typeof item.id         !== 'undefined' &&
            typeof item.value      !== 'undefined' &&
            typeof item.expires    !== 'undefined' &&
            typeof item.isLongTerm !== 'undefined')
        };

        /**
         * Add a TTL value to a date and return a new date to use as expiry value.
         * @private
         * @param {Number} [ttl]
         * @param {Date} [now]
         * @returns {Date}
         */
        var calculateExpiresDate = function calculateExpiresDate(ttl, now) {
            var _now = (typeof now === 'object' && now.toDateString) ? now : new Date();
            var _ttl = ttl || _options.ttl;
            return new Date(_now.valueOf() + _ttl);
        };

        /**
         * Create a new well-formed cache/storage object (used internally).
         * @private
         * @param {String} key
         * @param {*} value
         * @param {Boolean} [isLongTerm]
         * @returns {Object}
         */
        var createNewItem = function createNewItem(key, value, isLongTerm) {
            var _value = (typeof value === 'undefined') ? null : value;
            var _isLongTerm = !!isLongTerm;
            return {
                id: key,
                value: _value,
                expires: calculateExpiresDate((isLongTerm ? _options.ttl : _options.longTtl)),
                isLongTerm: _isLongTerm
            };
        };

        /**
         * Retrieve a value from the cache by the given key. If the resulting output is not a valid cache object, return null.
         * @private
         * @param {String} key
         * @returns {Object}
         */
        var getCacheItem = function getCacheItem(key) {
            if (!key) {
                if (_options.debug) console.warn('Please provide a key');
                return;
            }

            var item = _cache[key];
            return validateItem(item) ? item : null;
        };

        /**
         * Update the cache with the given cache item.
         * @private
         * @param {Object} item
         */
        var setCacheItem = function setCacheItem(item) {
            if (!validateItem(item)) {
                if (_options.debug) console.warn('Item was not set or properly formed: ', item);
                return;
            }

            _cache[item.id] = item;
        };

        /**
         * Remove an item from the cache by the given key.
         * @private
         * @param {String} key
         */
        var deleteCacheItem = function deleteCacheItem(key) {
            if (!key) {
                if (_options.debug) console.warn('Please provide a key');
                return;
            }

            if (typeof _cache[key] !== 'undefined') {
                _cache[key] = null;
                delete _cache[key];
            }
        };

        /**
         * Retrieve a cache object from storage by the given key.
         * @private
         * @param {String} key
         * @returns {Object}
         */
        var getStoreItem = function getStoreItem(key) {
            if (!key) {
                if (_options.debug) console.warn('Please provide a key');
                return;
            }

            var item = _cache[key];

            // default to session storage
            var storeMechanism = (validateItem(item) && item.isLongTerm) ? locSto : sesSto;
            var storeObj = JSON.parse(storeMechanism.getItem(_options.ns));

            if (!storeObj) {
                return null;
            }

            item = (typeof storeObj[key] === 'undefined') ? null : storeObj[key];

            return item;
        };

        /**
         * Atomically update storage with the given cache item.
         * @private
         * @param {Object} item
         */
        var setStoreItem = function setStoreItem(item) {
            if (!validateItem(item)) {
                if (_options.debug) console.warn('Item was not set or properly formed: ', item);
                return;
            }

            var storeMechanism = item.isLongTerm ? locSto : sesSto;
            var storeObj = JSON.parse(storeMechanism.getItem(_options.ns));

            if (!storeObj) {
                storeObj = {};
            }
            storeObj[item.id] = item;

            storeMechanism.setItem(_options.ns, JSON.stringify(storeObj));
        };

        /**
         * Remove an item from storage by the given key.
         * @private
         * @param {String} key
         */
        var deleteStoreItem = function deleteStoreItem(key) {
            if (!key) {
                if (_options.debug) console.warn('Please provide a key');
                return;
            }

            var item = _cache[key];

            if (!validateItem(item)) {
                if (_options.debug) console.warn('Item was not set or properly formed: ', item);
                return;
            }

            var storeMechanism = item.isLongTerm ? locSto : sesSto;
            var storeObj = JSON.parse(storeMechanism.getItem(_options.ns));

            storeObj[item.id] = null;
            delete storeObj[item.id];

            storeMechanism.setItem(_options.ns, JSON.stringify(storeObj));
        };

        /**
         * Determine whether a cache item is expired.
         * @private
         * @param {Object} item
         * @returns {Boolean}
         */
        var isExpired = function isExpired(item) {
            if (!item) {
                if (_options.debug) console.warn('Please provide an item');
                return;
            }

            var now = new Date();

            return new Date(item.expires.valueOf()) < now;
        };

        /**
         * Return the value of a cache object with the given key as an ID.
         * @method
         * @param {String} key
         * @returns {*}
         */
        this.get = function get(key) {
            var now = new Date();
            var storeObj;
            var item = getCacheItem(key);

            if (!item) {

                // prime cache
                storeObj = getStoreItem(key);
                if (!storeObj) {
                    storeObj = createNewItem(key, null);
                }
                setCacheItem(storeObj);
                item = getCacheItem(key);

                if (_options.debug) {
                    console.log('Initialized new cache item because blank "' + key + '"');
                    console.table(_cache);
                }

            } else if (isExpired(item)) {

                // refresh expired cached item from storage
                storeObj = getStoreItem(key);
                if (validateItem(storeObj)) {
                    item.value = storeObj.value;
                }
                item.expires = calculateExpiresDate((item.isLongTerm ? _options.ttl : _options.longTtl));
                setStoreItem(item);
                setCacheItem(item);

                if (_options.debug) {
                    console.log('Updated cache item because expired "' + key + '" (' + item.value + ')');
                    console.table(_cache);
                }

            } else {

                if (_options.debug) {
                    console.log('No cache init or update required, our data is still fresh.');
                    console.table(_cache);
                }

            }

            if (_options.debug) console.log('It is now ' + now.toString() + ' and _cache[' + key + '] expires at ', item.expires.toString());

            return item.value;
        };

        /**
         * Set the value of a cache object, resetting the expire time.
         * @method
         * @param {String} key
         * @param {*} value
         * @param {Boolean} [isLongTerm]
         */
        this.set = function set(key, value, isLongTerm) {
            var now = new Date();
            var item = getCacheItem(key);

            if (!item) {

                item = createNewItem(key, value, isLongTerm);
                if (_options.debug) {
                    console.log('Initialized new cache item because blank "' + key + '"');
                    console.table(_cache);
                }

            } else {

                item.value = value;
                item.expires = calculateExpiresDate((item.isLongTerm ? _options.ttl : _options.longTtl));
                if (_options.debug) {
                    console.log('Updated existing cache item "' + key + '" (' + value + ') : ' + now.toString());
                    console.table(_cache);
                }

            }

            // Ensure we never save the same key to two different types of storage.
            // If a different isLongTerm option is passed, delete the existing storage item.
            if (item.isLongTerm !== !!isLongTerm) {
                deleteStoreItem(key);
                item.isLongTerm = isLongTerm;
            }

            setStoreItem(item);
            setCacheItem(item);
        };

        /**
         * Destroy a cache item by key everywhere. If null is passed as the key and
         * true is passed as the optional second argument, the cache is completely reset.
         * @method
         * @param {String} key
         * @param {Boolean} [confirmDeleteAll]
         */
        this.del = function del(key, confirmDeleteAll) {
            // Provide the means to wipe the whole slate clean if desired.
            if (!key && confirmDeleteAll) {
                sesSto.removeItem(_options.ns);
                locSto.removeItem(_options.ns);
                _cache = null;
                _cache = {};
                if (_options.debug) console.log('Nuked the Fiji, kaboom!');
                return;
            }

            // Important to delete store item first so that the storage mechanism, if any, can be determined
            deleteStoreItem(key)
            deleteCacheItem(key)
        };

        /**
         * Return an object of all key-value pairs in the cache.
         * @method
         * @return {Object}
         */
        this.list = function list() {
            var valuesObj = {};
            var keys = Object.keys(_cache);
            for (var i = 0; i < keys.length; i++) {
                valuesObj[keys[i]] = this.get(keys[i]);
            }
            return valuesObj;
        };

    };

    return Fiji;

}));
<|endoftext|>


<commit_before>'use strict';

var esprima = require('esprima');
var select = require('JSONSelect');
var crypto = require('crypto');

function getHash(data) {
  return crypto
    .createHash('md5')
    .update(data)
    .digest('hex');
}

function index(indexes, source, loc, range) {
  var hash  =  getHash(source);
  var locS  =  loc.start;
  var locE  =  loc.end;

  // the exact same function could exist in multiple files, so we have to store all locations
  if (!indexes[hash]) indexes[hash] = [];
  indexes[hash].push({
      file  :  fullPath
    , start :  locS
    , end   :  locE
    , lines :  locE.line - locS.line
    , range :  range
  });
}

function rewriteDec (fn) {
  // toString() on a function converts 'function  foo (..' to 'function foo(..' so we need to do the same
  return fn.replace(/function +([^ ]+)[^\(]*\(/, 'function $1(');
}

function rewriteExp (fn) {
  // if it name is declared ('var foo = function foo (..'), treat like declaration
  return (/function +[^ (]+/).test(fn)
    ? rewriteDec(fn)
    : fn.replace(/function[^\(]*\(/, 'function (');
}

function locateNindex (indexes, ranges, locs, areDecs) {
  ranges.forEach(function (range, idx) {
    var start =  range[0];
    var end   =  range[1];

    var loc   =  locs[idx];
    var locS  =  loc.start;
    var locE  =  loc.end;

    var fn = js.slice(start, end);
    var source = areDecs ? rewriteDec(fn) : rewriteExp(fn);
    index(indexes, source, loc, range);
  });
}

/**
 * Indexes all functions in the given file content and adds them to the given indexes.
 *
 * @name exports
 * @function
 * @param js {String} the JavaScript file content
 * @param fullPath {String} full path at which the file can be found (optional, defaults to 'source.js')
 * @param indexes {Object} indexes that have been collected so far (optional, defaults to {})
 * @return {Object} the updated indexes
 */
var go = module.exports = function (js, fullPath, indexes) {
  fullPath = fullPath || 'source.js';
  indexes = indexes || {};
  var ast = esprima.parse(js, { range: true, loc: true });

  var decRanges = select.match('.type:val("FunctionDeclaration") ~ .range', ast)
  var decLocs = select.match('.type:val("FunctionDeclaration") ~ .loc', ast)

  var expRanges = select.match('.type:val("FunctionExpression") ~ .range', ast)
  var expLocs = select.match('.type:val("FunctionExpression") ~ .loc', ast);

  locateNindex(indexes, decRanges, decLocs, true);
  locateNindex(indexes, expRanges, expLocs, false);

  return indexes;
};

// Test
if (!module.parent) {
  var fs = require('fs');
  var fullPath = __dirname + '/test/fixtures/one-root-dec.js';
  var js = fs.readFileSync(fullPath, 'utf8');
  var fn = require(fullPath);

  var indexes = go(js, fullPath);
  console.log(indexes[getHash(fn.toString())]);
}
<commit_msg>fixing some missed arguments passing<commit_after>'use strict';

var esprima = require('esprima');
var select = require('JSONSelect');
var crypto = require('crypto');

function getHash(data) {
  return crypto
    .createHash('md5')
    .update(data)
    .digest('hex');
}

function index(indexes, source, fullPath, loc, range) {
  var hash  =  getHash(source);
  var locS  =  loc.start;
  var locE  =  loc.end;

  // the exact same function could exist in multiple files, so we have to store all locations
  if (!indexes[hash]) indexes[hash] = [];
  indexes[hash].push({
      file  :  fullPath
    , start :  locS
    , end   :  locE
    , lines :  locE.line - locS.line
    , range :  range
  });
}

function rewriteDec (fn) {
  // toString() on a function converts 'function  foo (..' to 'function foo(..' so we need to do the same
  return fn.replace(/function +([^ ]+)[^\(]*\(/, 'function $1(');
}

function rewriteExp (fn) {
  // if it name is declared ('var foo = function foo (..'), treat like declaration
  return (/function +[^ (]+/).test(fn)
    ? rewriteDec(fn)
    : fn.replace(/function[^\(]*\(/, 'function (');
}

function locateNindex (indexes, js, fullPath, ranges, locs, areDecs) {
  ranges.forEach(function (range, idx) {
    var start =  range[0];
    var end   =  range[1];

    var loc   =  locs[idx];
    var locS  =  loc.start;
    var locE  =  loc.end;

    var fn = js.slice(start, end);
    var source = areDecs ? rewriteDec(fn) : rewriteExp(fn);
    index(indexes, source, fullPath, loc, range);
  });
}

/**
 * Indexes all functions in the given file content and adds them to the given indexes.
 *
 * @name exports
 * @function
 * @param js {String} the JavaScript file content
 * @param fullPath {String} full path at which the file can be found (optional, defaults to 'source.js')
 * @param indexes {Object} indexes that have been collected so far (optional, defaults to {})
 * @return {Object} the updated indexes
 */
var go = module.exports = function (js, fullPath, indexes) {
  fullPath = fullPath || 'source.js';
  indexes = indexes || {};
  var ast = esprima.parse(js, { range: true, loc: true });

  var decRanges = select.match('.type:val("FunctionDeclaration") ~ .range', ast)
  var decLocs = select.match('.type:val("FunctionDeclaration") ~ .loc', ast)

  var expRanges = select.match('.type:val("FunctionExpression") ~ .range', ast)
  var expLocs = select.match('.type:val("FunctionExpression") ~ .loc', ast);

  locateNindex(indexes, js, fullPath, decRanges, decLocs, true);
  locateNindex(indexes, js, fullPath, expRanges, expLocs, false);

  return indexes;
};

// Test
if (!module.parent) {
  var fs = require('fs');
  var fullPath = __dirname + '/test/fixtures/one-root-dec.js';
  var js = fs.readFileSync(fullPath, 'utf8');
  var fn = require(fullPath);

  var indexes = go(js, fullPath);
  console.log(indexes[getHash(fn.toString())]);
}
<|endoftext|>


<commit_before>'use strict';

angular.module('adminApp')
  .directive('file', [function () {
    return {
      scope: {
        file: '='
      },
      link: function (scope, elem) {
        elem.bind('change', function (changeEvent) {
          var files = [];
          angular.forEach(changeEvent.target.files, function (file) {
            var isText = file.type.indexOf('text/') === 0;
            var reader = new FileReader();
            reader.file = file;
            reader.onload = function (e) {
              var data = e.target.result;
              if (!isText) {
                data = btoa(data);
              }
              files.push({
                type: file.type,
                name: file.name,
                body: data
              });
              if (files.length === changeEvent.target.files.length) {
                scope.$apply(function () {
                  scope.file = files;
                });
              }
            };
            if (isText) {
              reader.readAsText(file);
            } else {
              reader.readAsBinaryString(file);
            }
          });
        });
      }
    };
  }]);
<commit_msg>fix module name<commit_after>'use strict';

angular.module('file', [])
  .directive('file', [function () {
    return {
      scope: {
        file: '='
      },
      link: function (scope, elem) {
        elem.bind('change', function (changeEvent) {
          var files = [];
          angular.forEach(changeEvent.target.files, function (file) {
            var isText = file.type.indexOf('text/') === 0;
            var reader = new FileReader();
            reader.file = file;
            reader.onload = function (e) {
              var data = e.target.result;
              if (!isText) {
                data = btoa(data);
              }
              files.push({
                type: file.type,
                name: file.name,
                body: data
              });
              if (files.length === changeEvent.target.files.length) {
                scope.$apply(function () {
                  scope.file = files;
                });
              }
            };
            if (isText) {
              reader.readAsText(file);
            } else {
              reader.readAsBinaryString(file);
            }
          });
        });
      }
    };
  }]);
<|endoftext|>


<commit_before>var five = require("johnny-five");
var Edison = require("edison-io");
var board = new five.Board({
  io: new Edison()
});

board.on("ready", function() {
  var led = new five.Led(13),
      short = blink.bind(null, led, 500),
      long = blink.bind(null, led, 1000),
      sos = function (led, short, long) {

            };

  setInterval(function () {
    short(
      short.bind(null,
        short.bind(null,
          long.bind(null,
            long.bind(null,
              long.bind(null,
                short.bind(null,
                  short.bind(null,
                    short.bind(null, function () {})))))))));
  }, 15000);
});

function blink(led, interval, callback) {
  led.on();
  setTimeout(function () {
    led.off();
    setTimeout(function () {
      callback();
    }, 250)
  }, interval);
}
<commit_msg>Add web server<commit_after>var five = require("johnny-five");
var Edison = require("edison-io");
var http = require("http");

var server = http.createServer(function(request, response) {
  response.writeHead(200, {"Content-Type": "text/html"});
  response.write("<!DOCTYPE "html">");
  response.write("");
  response.write("");
  response.write("<title>Hello World Page!!!</title>");
  response.write("");
  response.write("");
  response.write("Hello World!");
  response.write("");
  response.write("");
  response.end();
});

server.listen(80);

var board = new five.Board({
  io: new Edison()
});

board.on("ready", function() {
  var led = new five.Led(13),
      short = blink.bind(null, led, 500),
      long = blink.bind(null, led, 1000),
      sos = function (led, short, long) {

            };

  setInterval(function () {
    short(
      short.bind(null,
        short.bind(null,
          long.bind(null,
            long.bind(null,
              long.bind(null,
                short.bind(null,
                  short.bind(null,
                    short.bind(null, function () {})))))))));
  }, 15000);
});

function blink(led, interval, callback) {
  led.on();
  setTimeout(function () {
    led.off();
    setTimeout(function () {
      callback();
    }, 250)
  }, interval);
}
<|endoftext|>


<commit_before>/*
 *
*/

var flags = [];

var Flag = function(canvas, text) {
	this.canvas = canvas
	this.context = canvas.getContext("2d");
	this.text = text

	this.textbuf = document.createElement("canvas");
	//document.body.appendChild(this.textbuf);
	this.textcontext = this.textbuf.getContext("2d");
	var tm = this.textcontext.measureText(this.text);
	this.textbuf.width = tm.width;
	this.textbuf.height = 20;
	this.textcontext.textAlign = "center";
	this.textcontext.textBaseline = "middle";
	this.textcontext.fillText(text, this.textbuf.width / 2, this.textbuf.height / 2, this.textbuf.width);

	this.dw = this.canvas.width / this.textbuf.width;

	this.radius = (this.canvas.height - this.textcontext.canvas.height) / 4;

	this.angle = 0.0;

	this.render = function() {
		var src = this.textcontext;
		var dst = this.context;
		var angle = this.angle;
		var cy = (dst.canvas.height - src.canvas.height) / 2;
		dst.clearRect(0, 0, dst.canvas.width, dst.canvas.height);
		for(var x = 0; x < src.canvas.width; ++x) {
			var dx = x * this.dw;
			var dy = this.radius * Math.sin(angle) * Math.cos(angle / 3) * Math.sin(angle / 5);
			dst.drawImage(src.canvas, x, 0, 1, src.canvas.height, dx, dy, this.dw, dst.canvas.height);
			angle += 0.2;
		}
	};
};

// Find all flag-classed canvases in the page.
var canvases = document.body.getElementsByTagName("canvas");
for(var i = 0; i < canvases.length; ++i) {
	if(canvases[i].className == "flag") {
		var text = canvases[i].getAttribute("flagtext");
		if(text) {
			flags.push(new Flag(canvases[i], text));
		}
	}
}

function renderFlags() {
	requestAnimationFrame(renderFlags);
	for(var i = 0; i < flags.length; ++i) {
		flags[i].render();
		flags[i].angle += 0.1;
/*		while(flags[i].angle >= 2 * Math.PI) {
			flags[i].angle -= 2 * Math.PI;
		}
*/	}
}

renderFlags();
<commit_msg>Implemented customizable "effect" setting on the flag element.<commit_after>/*
 *
*/

var flags = [];

var Flag = function(canvas, text, fx) {
	this.canvas = canvas
	this.context = canvas.getContext("2d");
	this.text = text

	this.textbuf = document.createElement("canvas");
	//document.body.appendChild(this.textbuf);
	this.textcontext = this.textbuf.getContext("2d");
	var tm = this.textcontext.measureText(this.text);
	this.textbuf.width = tm.width;
	this.textbuf.height = 20;
	this.textcontext.textAlign = "center";
	this.textcontext.textBaseline = "middle";
	this.textcontext.fillText(text, this.textbuf.width / 2, this.textbuf.height / 2, this.textbuf.width);

	// Analyze the fx string, which controls the flag effect. Very basic.
	// Use e.g. "s,s/3,s*5" to get sin(angle) * sin(angle / 3) * sin(angle * 5)
	// No support for scaling the sin itself yet.
	var FlagFxTerm = function(fxp) {
		this.func = fxp[0] == "s" ? Math.sin : Math.cos;
		this.scale = 1;
		if(fxp[1] == "/") {
			this.scale = 1.0 / Number(fxp.substring(2));
		}
		else if(fxp[1] == "*") {
			this.scale = Number(fxp.substring(2));
		}
		this.eval = function(angle) {
			return this.func(angle * this.scale);
		};
	};
	this.fxterms = []
	if(fx.length > 0) {
		var fxp = fx.split(",");
		for(var i = 0; i < fxp.length; ++i) {
			this.fxterms.push(new FlagFxTerm(fxp[i]));
		}
	}

	this.dw = this.canvas.width / this.textbuf.width;
	this.radius = (this.canvas.height - this.textcontext.canvas.height) / 4;
	this.angle = 0.0;

	this.render = function() {
		var src = this.textcontext;
		var dst = this.context;
		var angle = this.angle;
		var cy = (dst.canvas.height - src.canvas.height) / 2;
		dst.clearRect(0, 0, dst.canvas.width, dst.canvas.height);
		for(var x = 0; x < src.canvas.width; ++x) {
			var dx = x * this.dw;
			var dy = this.radius;
			// Apply the effect terms to the radius, this makes the flag wave.
			for(var i = 0; i < this.fxterms.length; ++i) {
				dy *= this.fxterms[i].eval(angle);
			}
			dst.drawImage(src.canvas, x, 0, 1, src.canvas.height, dx, dy, this.dw + 0.5, dst.canvas.height);
			angle += 0.2;
		}
	};
};

// Find all flag-classed canvases in the page.
var canvases = document.body.getElementsByTagName("canvas");
for(var i = 0; i < canvases.length; ++i) {
	if(canvases[i].className == "flag") {
		var text = canvases[i].getAttribute("flagtext");
		if(text) {
			var fx = canvases[i].getAttribute("flagfx");
			flags.push(new Flag(canvases[i], text, fx));
		}
	}
}

// Render all the flags on the page.
function renderFlags() {
	requestAnimationFrame(renderFlags);
	for(var i = 0; i < flags.length; ++i) {
		flags[i].render();
		flags[i].angle += 0.1;
/*		while(flags[i].angle >= Math.PI) {
			flags[i].angle -= Math.PI;
		}
*/	}
}

renderFlags();
<|endoftext|>


<commit_before>function compose() {
    fs = arguments;
    return function(x) {
        for(var i in fs) {
            var f = fs[fs.length - i - 1];
            x = f.apply(null, [x]);
        }
        return x;
    }
}

function squish(x1, x2) {
    for (var key in x2) {
        x1[key] = x2[key];
    }
    return x1;
}

function merge(x1, x2) {
    return squish(squish({}, x1), x2);
}

function Person(name) {
    return {_name: name};
}

function Titled(x) {
    return merge(x, {_title: "Dr"});
}

function Friendly(x) {
    return merge(x, {hello: function() { return "Hi, I'm " + x._title + " " + x._name;}});
}

var TitledPerson = compose(Titled, Person);
var Friend = compose(Friendly, Titled, Person);
var tony = new Friend("Tony");

console.log(tony);
console.log(tony.hello());
<commit_msg>Make squish private as it's dangerous.<commit_after>function compose() {
    fs = arguments;
    return function(x) {
        for(var i in fs) {
            var f = fs[fs.length - i - 1];
            x = f.apply(null, [x]);
        }
        return x;
    }
}

function merge(x1, x2) {
    function squish(under, over) {
        for (var key in over) {
            under[key] = over[key];
        }
        return under;
    }
    return squish(squish({}, x1), x2);
}

function Person(name) {
    return {_name: name};
}

function Titled(x) {
    return merge(x, {_title: "Dr"});
}

function Friendly(x) {
    return merge(x, {hello: function() { return "Hi, I'm " + x._title + " " + x._name;}});
}

var TitledPerson = compose(Titled, Person);
var Friend = compose(Friendly, Titled, Person);
var tony = new Friend("Tony");

console.log(tony);
console.log(tony.hello());
<|endoftext|>


<commit_before>"use strict";

if(typeof exports === 'undefined'){
    var exports = window.fold = {};
}

(function ($f) {

    var isEmpty = function (arr) {
        return typeof arr === 'undefined' || arr.length === 0;
    };

    var hdtl = function (arr) {
        // Check if array is not empty
        return {
            'hd': arr[0],
            'tl': arr.slice(1)
        };
    };

    var add = function (a, b) {
        return a + b;
    };

    var fill = function (e, n) {
        var arr = [];
        for (var i = 0; i < n; i++) {
            arr.push(e);
        }
        return arr;
    };

    $f.foldL = function _foldL (arr, f, init) {
        if (isEmpty(arr)) {
            return init;
        }
        else {
            var p = hdtl(arr);
            return f(_foldL(p.tl, f, init), p.hd);
        }
    };

    $f.foldR = function _foldR (arr, f, init) {
        if (isEmpty(arr)) {
            return init;
        }
        else {
            var p = hdtl(arr);
            return _foldR(p.tl, f, f(init, p.hd));
        }
    };

    $f.size = function (arr) {
        return $f.foldL(arr, function (a, x) { return a + 1; }, 0);
    };

    $f.sum = function (arr) {
        return $f.foldL(arr, add, 0);
    };

    $f.forEach = function (arr, f) {
        return $f.foldR(arr, function (a, x) { f(x); }, undefined);
    };

    $f.map = function (arr, f) {
        return $f.foldR(arr, function (a, x) {
            a.push(f(x));
            return a;
        }, []);
    };

    $f.filter = function (arr, f) {
        return $f.foldR(arr, function (a, x) {
            if (f(x)) {
                a.push(x);
            }

            return a;
        }, []);
    };

    $f.drop = function (arr, n) {
        return $f.foldR(arr, function (a, x) {
            var acc = a.acc,
                count = a.count;

            if (count % n !== 0) {
                acc.push(x);
            }

            return {
                'acc': acc,
                'count': count + 1
            };
        }, { 'acc': [], 'count': 1 }).acc; // Get just the accumulator (no count)
    };

    $f.partition = function (arr, f) {
        return $f.foldR(arr, function (a, x) {

            if (f(x)) {
                a.T.push(x);
            }
            else {
                a.F.push(x);
            }

            return a;

        }, {'T': [], 'F': []});
    };

    $f.replicate = function (arr, n) {
        return $f.foldR(arr, function (a, x) {
            a.push(fill(x, n));

            return a;
        }, []);
    };

})(typeof exports === 'undefined'? window.fold = {} : exports);

var f = require('./fold');
var n = f.replicate([1, 2, 3, 4], 3);

console.log(n);<commit_msg>Added more fn<commit_after>"use strict";

if(typeof exports === 'undefined'){
    var exports = window.fold = {};
}

(function ($f) {

    var isEmpty = function (arr) {
        return typeof arr === 'undefined' || arr.length === 0;
    };

    var destructor = function (arr) {
        // Check if array is not empty
        return {
            'hd': arr[0],
            'tl': arr.slice(1)
        };
    };

    var add = function (a, b) {
        return a + b;
    };

    var fill = function (e, n) {
        var arr = [];
        for (var i = 0; i < n; i++) {
            arr.push(e);
        }
        return arr;
    };

    $f.foldL = function _foldL (arr, f, init) {
        if (isEmpty(arr)) {
            return init;
        }
        else {
            var p = destructor(arr);
            return f(_foldL(p.tl, f, init), p.hd);
        }
    };

    $f.foldR = function _foldR (arr, f, init) {
        if (isEmpty(arr)) {
            return init;
        }
        else {
            var p = destructor(arr);
            return _foldR(p.tl, f, f(init, p.hd));
        }
    };

    $f.size = function (arr) {
        return $f.foldL(arr, function (a, x) { return a + 1; }, 0);
    };

    $f.sum = function (arr) {
        return $f.foldL(arr, add, 0);
    };

    $f.forEach = function (arr, f) {
        return $f.foldR(arr, function (a, x) { f(x); }, undefined);
    };

    $f.map = function (arr, f) {
        return $f.foldR(arr, function (a, x) {
            a.push(f(x));
            return a;
        }, []);
    };

    $f.filter = function (arr, f) {
        return $f.foldR(arr, function (a, x) {
            if (f(x)) {
                a.push(x);
            }

            return a;
        }, []);
    };

    $f.drop = function (arr, n) {
        var count = 1;

        return $f.foldR(arr, function (a, x) {
            if (count % n !== 0) {
                a.push(x);
            }
            count++;

            return a;
        }, []);
    };

    $f.take = function (arr, n) {
        var count = 1;

        return $f.foldR(arr, function (a, x) {
            if (count % n === 0) {
                a.push(x);
            }
            count++;

            return a;
        }, []);
    };

    $f.partition = function (arr, f) {
        return $f.foldR(arr, function (a, x) {

            if (f(x)) {
                a.T.push(x);
            }
            else {
                a.F.push(x);
            }

            return a;

        }, {'T': [], 'F': []});
    };

    $f.replicate = function (arr, n) {
        return $f.foldR(arr, function (a, x) {
            a.push(fill(x, n));

            return a;
        }, []);
    };

    $f.elimConsec = function (arr) {
        if (isEmpty(arr)) {
            return arr;
        }

        var cur = destructor(arr).hd,
            count = 0;

        return $f.foldR(arr, function (a, x) {
            if (count === 0) {
                a.push(x);
            }
            else {
                if (x !== cur) {
                    a.push(x);
                }
            }

            cur = x;
            count++;
            return a;
        }, []);
    };

    $f.max = function (arr) {

    };

    $f.min = function (arr) {

    };

})(typeof exports === 'undefined'? window.fold = {} : exports);

var f = require('./fold');
var n = f.elimConsec([]);

console.log(n);<|endoftext|>


<commit_before>// this one gets more base words
// final logging/testing improvements

function f_four(str) {
  return ntrprt(parse(str))

  function ntrprt(program, stack, dict) {
    stack = stack || []

    if(!dict) {
      dict = {}
      dict['pick']  = function(stack) {p=stack.pop(); stack.push(stack[stack.length-p-1]); return stack}
      dict['roll']  = function(stack) {p=stack.pop(); x=stack[stack.length-p-1]; stack.splice(stack.length-p-1, 1); stack.push(x); return stack}

      addword('dup',  '0 pick', dict)
      addword('over', '1 pick', dict)
      addword('swap', '1 roll', dict)
      addword('rot',  '2 roll', dict)
      addword('tuck', 'swap 1 pick', dict)
      dict['drop'] = function(stack) {stack.pop(); return stack}

      var ops  = ['+', '*', '-', '/', '%', '^', '|', '&', '||', '&&', '<', '>', '<<', '>>', '==']
      ops.forEach(function(op) {
        dict[op] = function(stack) {
          var top=stack.pop(); stack.push(eval(stack.pop() + op + top)); return stack } })
    }

    function eatword(dict, program, pc) {
      var stop = program.indexOf(';', pc)
      var name = program[pc+1]
      var sub = program.slice(pc+2, stop)
      addword(name, sub, dict)
      pc = stop
      return [dict, program, pc]
    }

    function addword(name, sub, dict) {
      if(typeof sub == 'string') sub = parse(sub)
      dict[name] = function(stack) {return ntrprt(sub, stack, dict)}
    }

    var pc = 0, max = program.length
    while(pc < max) {
      var word = program[pc]
      if(word == ':') {
        out = eatword(dict, program, pc)                  // use ES6 destructuring
        dict = out[0]
        program = out[1]
        pc = out[2]
      }
      else if(+word == word)
        stack.push(+word)                                 // numbers go on the stack
      else
        stack = dict[word](stack)                         // funs can be any arity
      pc++
    }
    return stack
  }

  function parse(str) {
    str = eatcomments(str)
    return str.split(/\s+/)
  }

  function eatcomments(str) {
    var arr = str.split('')
    var mode = 'add'
    return arr.reduce(function(acc, char) {
      if(char == '(') mode = 'paren'                      // TODO: count depth
      if(mode == 'add') acc += char
      if(char == ')') mode = 'add'
      return acc
    }, "")
  }
}

var test = function(str, res) {
  var error = console.error.bind(console)
  var log   = console.log.bind(console)
  var name = 'f_four'
  var fun  = name+'("'+str+'")'
  var out  = eval(fun)
  var say  = JSON.stringify(out) == JSON.stringify(res) ? log : error
  say(fun, out)
}

test("5.2 2 -", [3.2])                                    // decimals and subtraction are still fine
test("1 2 + 3 *", [9])                                    // interleaved operators are fine
test("3 4 drop dup *", [9])                               // keywords are still fine
test("3 : dd dup dup ; dd * *", [27])                     // new words!
test(": dd dup dup ; : ddd dd dup ; 3 ddd + + +", [12])   // new words in new words!
test(": triple 3 * ; 7 triple", [21])                     // note that defs are global and flat (not nested)

<commit_msg>trim + lowercase; 50% less eval; fancy new tests<commit_after>// this one gets more base words
// final logging/testing improvements

function f_four(str) {
  return ntrprt(parse(str))

  function ntrprt(program, stack, dict) {
    stack = stack || []

    if(!dict) {
      dict = {}
      dict['pick']  = function(stack) {p=stack.pop(); stack.push(stack[stack.length-p-1]); return stack}
      dict['roll']  = function(stack) {p=stack.pop(); x=stack[stack.length-p-1]; stack.splice(stack.length-p-1, 1); stack.push(x); return stack}

      addword('dup',  '0 pick', dict)
      addword('over', '1 pick', dict)
      addword('swap', '1 roll', dict)
      addword('rot',  '2 roll', dict)
      addword('tuck', 'swap 1 pick', dict)
      dict['drop'] = function(stack) {stack.pop(); return stack}

      var ops  = ['+', '*', '-', '/', '%', '^', '|', '&', '||', '&&', '<', '>', '<<', '>>', '==']
      ops.forEach(function(op) {
        dict[op] = function(stack) {
          var top=stack.pop(); stack.push(eval(stack.pop() + op + top)); return stack } })
    }

    function eatword(dict, program, pc) {
      var stop = program.indexOf(';', pc)
      var name = program[pc+1]
      var sub = program.slice(pc+2, stop)
      addword(name, sub, dict)
      pc = stop
      return [dict, program, pc]
    }

    function addword(name, sub, dict) {
      if(typeof sub == 'string') sub = parse(sub)
      dict[name] = function(stack) {return ntrprt(sub, stack, dict)}
    }

    var pc = 0, max = program.length
    while(pc < max) {
      var word = program[pc]
      if(word == ':') {
        out = eatword(dict, program, pc)                  // use ES6 destructuring
        dict = out[0]
        program = out[1]
        pc = out[2]
      }
      else if(+word == word)
        stack.push(+word)                                 // numbers go on the stack
      else
        stack = dict[word](stack)                         // funs can be any arity
      pc++
    }
    return stack
  }

  function parse(str) {
    str = eatcomments(str)
    return str.trim().toLowerCase().split(/\s+/)
  }

  function eatcomments(str) {
    var arr = str.split('')
    var mode = 'add'
    return arr.reduce(function(acc, char) {
      if(char == '(') mode = 'paren'                      // TODO: count depth
      if(mode == 'add') acc += char
      if(char == ')') mode = 'add'
      return acc
    }, "")
  }
}

var test = function(str, res) {
  var error = console.error.bind(console)
  var log   = console.log.bind(console)
  var name = 'f_four'
  var fun  = name+'("'+str+'")'
  var out  = window[name](str)
  var say  = JSON.stringify(out) == JSON.stringify(res) ? log : error
  say(fun, out)
}

test("5.2 2 -", [3.2])                                    // decimals and subtraction are still fine
test("1 2 + 3 *", [9])                                    // interleaved operators are fine
test("3 4 drop dup *", [9])                               // keywords are still fine
test("3 : dd dup dup ; dd * *", [27])                     // new words!
test(": dd dup dup ; : ddd dd dup ; 3 ddd + + +", [12])   // new words in new words!
test(": triple 3 * ; 7 triple", [21])                     // note that defs are global and flat (not nested)

test("2 5 73 -16 2 roll", [2, 73, -16, 5])
test("2 5 73 -16 3 pick", [2, 5, 73, -16, 2])
test("2 5 73 -16 tuck", [2, 5, -16, 73, -16])
test("5 2 ( asdf 123 ) -", [3])
test(': SQUARED   ( a -- a*a )     DUP *  ;           \
                                                      \
              : SUM-OF-SQUARES   ( a b -- a*a+b*b )   \
                   SQUARED            ( -- a b*b)     \
                   SWAP               ( -- b*b a)     \
                   SQUARED            ( -- b*b a*a)   \
                   +                  ( -- b*b + a*a) \
              ;                                       \
5 7 SUM-OF-SQUARES                                    \
', [74])
<|endoftext|>


<commit_before>/* Version 1.2.0 */

(function (window, factory) {
  'use strict';

  if (typeof define === 'function' && define.amd) {
    define([], factory(window));
  } else if (typeof exports === 'object') {
    module.exports = factory(window);
  } else {
    window.Fryr = factory(window);
  }

})(window, function factory(window) {
  'use strict';

  /**
   * Remove all traces of a hash if it's blank
   * @private
   * @param {String} hash - The existing hash
   * @see {@link http://stackoverflow.com/a/5298684}
   * @fires history.pushState OR window.onhashchange
   */
  function removeHashIfBlank(hash) {
    if(hash === '#') {
      // Modern browsers
      if ('pushState' in history) {
        history.pushState('', document.title, window.location.pathname + window.location.search);

      } else {
        // Prevent scrolling by storing the page's current scroll offset
        var scrollV = document.body.scrollTop;
        var scrollH = document.body.scrollLeft;

        window.location.hash = '';

        // Restore the scroll offset
        document.body.scrollTop = scrollV;
        document.body.scrollLeft = scrollH;
      }

    } else {
      // If the hash isn't blank, fire onhashchange
      window.location.hash = hash;

    }
  }

  /**
   * Delete value based on key
   * @private
   * @param {String} key - Param to target
   * @param {String|Number} value - Value to delete from param
   */
  function removeValue(key, value) {
    var hash = window.location.hash;
    // check for key, anything between key and value, the value itself, and optionally the trailing comma
    var regex_for_value = new RegExp('(' + key + '=.*)(' + value + ',?)');
    // results come back [<search through value>, <search before value>, <value>]
    var regex_match = hash.match(regex_for_value);
    // replace <search through value> with everything before <value>
    // Key is included in search in case multiple keys have the same value
    hash = hash.replace(regex_match[0], regex_match[1]);

    // Remove trailing commas
    hash = hash.replace(/,&/g, '&');
    hash = hash.replace(/,$/, '');
    hash = hash.replace(/=\,/g, '=');

    removeHashIfBlank(hash);
  }

  /**
   * Add value based on key
   * @private
   * @param {String} key - Param to target
   * @param {String|Number} value - Value to add to param
   * @param {Boolean} should_replace_value - if false, value will be appended to the param
   * @fires window.onhashchange
   */
  function addValue(key, value, should_replace_value) {
    var hash = window.location.hash;

    var old_value = param(key);
    var new_value;

    // If it's blank or is the value of the next param
    if(old_value.charAt(0) === '&' || old_value === '') {
      old_value = key + '=';
      new_value = old_value + value;

    } else {
      old_value = key + '=' + old_value;

      // If the value of the param should be replaced, don't append it to the existing value
      new_value = should_replace_value ? (key + '=' + value) : (old_value + ',' + value);
    }

    hash = hash.replace(old_value, new_value);

    window.location.hash = hash;
  }

  /**
   * Remove key from hash. Key's value must be removed prior to executing this function
   * @private
   * @param {String} key - Key to search and destroy
   */
  function removeKey(key) {
    var hash = window.location.hash;
    var key_search = new RegExp('[?&]' + key + '=', 'g');

    hash = hash.replace(key_search, '');
    // if initial key removed, replace ampersand with question
    hash = hash.replace('#&', '#?');

    removeHashIfBlank(hash);
  }

  /**
   * @private
   * @see {@link Fryr#param documentation in the public `param` function}
   */
  function param(key) {
    if(!window.location.hash) {
      return '';
    }

    var hash = window.location.hash;
    var search = new RegExp('#.*[?&]' + key + '=([^&]+)(&|$)');
    var key_value = hash.match(search);

    return (key_value ? key_value[1] : '');
  }

  /**
   * Apply value to variable if it has none
   * @private
   * @param {*} variable Variable to set default to
   * @param {*} value - Default value to attribute to variable
   * @return {*} Existing value or passed value argument
   */
  function setDefault(variable, value){
    return (typeof variable === 'undefined') ? value : variable;
  }

  /**
   * Remove key/value if present in hash; add key/value if not present in hash
   * @private
   * @param {String} key - Param key to query against
   * @param {String|Number} value - Value for param key
   * @param {Boolean} key_is_required - If the key is not required, it will be removed from the hash
   * @param {Boolean} should_replace_value - If false, value will be appended to the key
   * @see {@link Fryr#update}
   * @see {@link Fryr#append}
   * @fires window.onhashchange
   */
  function update(key, value, key_is_required, should_replace_value) {
    var hash = window.location.hash;

    // Ensure key exists in the hash
    if(hash.indexOf(key) !== -1) {
      var key_value = param(key);

      var regex_for_value = new RegExp(value, 'g');

      // If key_value contains the new value
      if(regex_for_value.test(key_value)) {

        // If key is required, swap it out
        if(key_is_required) {
          addValue(key, value, should_replace_value);

        } else {

          // If the value is blank, remove the original value from the key
          if(value === '') {
            removeValue(key, key_value);

          // Otherwise remove the vanilla value
          } else {
            if(key_value !== value) {
              removeValue(key, value);
            } else {
              console.log('suppp')
            }

          }

          // If key's value is blank, remove it from hash
          if(param(key) === '') {
            removeKey(key);
          }

        }

      // key_value does not contain the new value
      } else {
        addValue(key, value, should_replace_value);

      }

    // Add key if it doesn't exist
    } else {

      if(window.location.hash) {
        window.location.hash += '&' + key + '=' + value;
      } else {
        // Use a question mark if first key
        window.location.hash = '?' + key + '=' + value;
      }

    }
  }

  /**
   * Callback with new params. Callback defined in initialization
   * @private
   * @fires hashChangeCallback
   */
  function privateHashChange() {
    var params = this.parse();
    this.callback.call(this, params);
  }

  /**
   * Call once to initialize filtering
   * @param {Function} hashChangeCallback - Called on every hashchange
   *   @param {Object} Updated params
   * @param {Object} [defaults={}] - Key/value pairs for values that should be added on init. Pass {} to skip defaults
   * @param {Boolean} [call_on_init=true] - Execute callback on initialization. Always true if defaults is supplied
   * @return {Fryr}
   */
  function Fryr(hashChangeCallback, defaults, call_on_init) {
    defaults = setDefault(defaults, {});
    call_on_init = setDefault(call_on_init, true);

    this.callback = hashChangeCallback;

    /**
     * Very important object holder
     * @type {Object}
     */
    this.params = {};

    window.addEventListener('hashchange', privateHashChange.bind(this));

    // Apply defaults (if present) to hash, which will file window.onhashchange
    if( Object.keys(defaults).length && window.location.hash === '' ) {
      this.merge(defaults, true);

    // Execute the callback on load
    } else if(call_on_init) {
      privateHashChange.call(this);

    }

    return this;
  }

  /**
   * Replace key/value if present in hash; add key/value if not present in hash
   * @param {String} key - Param key to query against
   * @param {String|Number} value - Value for param key
   * @param {Boolean} [key_is_required=false] - if the key is not required, it will be removed from the hash
   * @see {@link Fryr#append}
   */
  Fryr.prototype.update = function(key, value, key_is_required) {
    key_is_required = setDefault(key_is_required, false);
    update(key, value, key_is_required, true);
  };

  /**
   * Add value to key's value in a comma-delineated list if it's not present in hash
   * @param {String} key - Param key to query against
   * @param {String|Number} value - Value for param key
   * @see {@link Fryr#update}
   */
  Fryr.prototype.append = function(key, value) {
    update(key, value, false, false);
  };

  /**
   * Evaluate the hash
   * @return {Object} Key/value hash of the hash broken down by params
   */
  Fryr.prototype.parse = function() {
    var hash = window.location.hash;
    var params;

    // clear zombie keys and values
    this.params = {};

    if(window.location.hash && /\?/g.test(hash)) {
      params = hash.split('?')[1];
      params = params.split('&');

      // Separate params into key values
      for(var i = 0; i < params.length; i++) {
        var key_value = params[i].split('=');
        var key = key_value[0];
        var value = key_value[1];

        this.params[key] = value;
      }
    }

    return this.params;
  };

  /**
   * Change a JSON object into a string for the hash
   * @param {Object|String} obj - object to convert
   * @return {String|Boolean} For use in window.location.hash. Returns false if param is not object or string
   */
  Fryr.prototype.convert = function(obj) {
    if( obj.constructor === String ) {
      obj = JSON.parse(obj);
    }

    // Escape if we're not dealing with an object
    if( obj.constructor !== Object ) {
      return false;
    }

    var keys = Object.keys(obj);
    // Set start with a ?
    var new_hash = '?';

    // Loop through all keys in the obj
    for(var i = 0; i < keys.length; i++) {
      var key = keys[i];
      var value = obj[ key ];

      if( value.constructor === Array ) {
        value = value.join(',');
      }

      // On next key, if it isn't the first, precede with an ampersand
      if(new_hash !== '?') {
        new_hash += '&';
      }

      // Append key/value to new_hash
      new_hash += key + '=' + value;
    }

    return new_hash;
  };

  /**
   * Wipe out or selectively replace keys in params
   * @param {Object|String} obj - Query to replace
   * @param {Boolean} [replace_all=false] - Whether or not to blast existing params away or replace only changed keys
   * @fires window.onhashchange
   * @return {String} The new hash
   */
  Fryr.prototype.merge = function(obj, replace_all) {
    replace_all = setDefault(replace_all, false);

    // If it's a string, convert to an object
    if( obj.constructor === String ) {
      obj = JSON.parse(obj);
    }

    // Override or add key values from existing params and put them into the object
    if( !replace_all ) {
      var new_params = this.parse();

      var keys = Object.keys(new_params);

      for(var i = 0; i < keys.length; i++) {
        var key = keys[i];
        var value = new_params[ key ];

        if(!obj.hasOwnProperty(key)) {
          obj[key] = value;
        }
      }
    }

    // Change hash to string; if replace_all is false, original value is used
    var new_hash = this.convert(obj);

    window.location.hash = '#' + new_hash;

    return new_hash;
  };

  /**
   * Retrieve a key's value
   * @param {String} key - Param to target
   * @example
   * window.location.hash = '?color=blue'
   * fryr.param('color') // => 'blue'
   * @return {String} The value of the key
   */
  Fryr.prototype.param = function(key) {
    return param(key);
  };

  /**
   * Determine if param is blank or undefined
   * @param {String} key - Param to target
   * @return {Boolean}
   */
  Fryr.prototype.paramPresent = function(key) {
    var value = this.params[key];
    return (typeof value !== 'undefined' && value !== '');
  };

  /**
   * Destroy current initialization, unbind hashchange listener, and reset the hash to an empty state
   * @param {Boolean} [retain_hash=false] - Keep items in hash
   */
  Fryr.prototype.destroy = function(retain_hash){
    retain_hash = setDefault(retain_hash, false);

    window.removeEventListener('hashchange', privateHashChange);

    if(!retain_hash) {
      window.location.hash = '';
    }
  };

  return Fryr;

});
<commit_msg>remove console.log<commit_after>/* Version 1.2.0 */

(function (window, factory) {
  'use strict';

  if (typeof define === 'function' && define.amd) {
    define([], factory(window));
  } else if (typeof exports === 'object') {
    module.exports = factory(window);
  } else {
    window.Fryr = factory(window);
  }

})(window, function factory(window) {
  'use strict';

  /**
   * Remove all traces of a hash if it's blank
   * @private
   * @param {String} hash - The existing hash
   * @see {@link http://stackoverflow.com/a/5298684}
   * @fires history.pushState OR window.onhashchange
   */
  function removeHashIfBlank(hash) {
    if(hash === '#') {
      // Modern browsers
      if ('pushState' in history) {
        history.pushState('', document.title, window.location.pathname + window.location.search);

      } else {
        // Prevent scrolling by storing the page's current scroll offset
        var scrollV = document.body.scrollTop;
        var scrollH = document.body.scrollLeft;

        window.location.hash = '';

        // Restore the scroll offset
        document.body.scrollTop = scrollV;
        document.body.scrollLeft = scrollH;
      }

    } else {
      // If the hash isn't blank, fire onhashchange
      window.location.hash = hash;

    }
  }

  /**
   * Delete value based on key
   * @private
   * @param {String} key - Param to target
   * @param {String|Number} value - Value to delete from param
   */
  function removeValue(key, value) {
    var hash = window.location.hash;
    // check for key, anything between key and value, the value itself, and optionally the trailing comma
    var regex_for_value = new RegExp('(' + key + '=.*)(' + value + ',?)');
    // results come back [<search through value>, <search before value>, <value>]
    var regex_match = hash.match(regex_for_value);
    // replace <search through value> with everything before <value>
    // Key is included in search in case multiple keys have the same value
    hash = hash.replace(regex_match[0], regex_match[1]);

    // Remove trailing commas
    hash = hash.replace(/,&/g, '&');
    hash = hash.replace(/,$/, '');
    hash = hash.replace(/=\,/g, '=');

    removeHashIfBlank(hash);
  }

  /**
   * Add value based on key
   * @private
   * @param {String} key - Param to target
   * @param {String|Number} value - Value to add to param
   * @param {Boolean} should_replace_value - if false, value will be appended to the param
   * @fires window.onhashchange
   */
  function addValue(key, value, should_replace_value) {
    var hash = window.location.hash;

    var old_value = param(key);
    var new_value;

    // If it's blank or is the value of the next param
    if(old_value.charAt(0) === '&' || old_value === '') {
      old_value = key + '=';
      new_value = old_value + value;

    } else {
      old_value = key + '=' + old_value;

      // If the value of the param should be replaced, don't append it to the existing value
      new_value = should_replace_value ? (key + '=' + value) : (old_value + ',' + value);
    }

    hash = hash.replace(old_value, new_value);

    window.location.hash = hash;
  }

  /**
   * Remove key from hash. Key's value must be removed prior to executing this function
   * @private
   * @param {String} key - Key to search and destroy
   */
  function removeKey(key) {
    var hash = window.location.hash;
    var key_search = new RegExp('[?&]' + key + '=', 'g');

    hash = hash.replace(key_search, '');
    // if initial key removed, replace ampersand with question
    hash = hash.replace('#&', '#?');

    removeHashIfBlank(hash);
  }

  /**
   * @private
   * @see {@link Fryr#param documentation in the public `param` function}
   */
  function param(key) {
    if(!window.location.hash) {
      return '';
    }

    var hash = window.location.hash;
    var search = new RegExp('#.*[?&]' + key + '=([^&]+)(&|$)');
    var key_value = hash.match(search);

    return (key_value ? key_value[1] : '');
  }

  /**
   * Apply value to variable if it has none
   * @private
   * @param {*} variable Variable to set default to
   * @param {*} value - Default value to attribute to variable
   * @return {*} Existing value or passed value argument
   */
  function setDefault(variable, value){
    return (typeof variable === 'undefined') ? value : variable;
  }

  /**
   * Remove key/value if present in hash; add key/value if not present in hash
   * @private
   * @param {String} key - Param key to query against
   * @param {String|Number} value - Value for param key
   * @param {Boolean} key_is_required - If the key is not required, it will be removed from the hash
   * @param {Boolean} should_replace_value - If false, value will be appended to the key
   * @see {@link Fryr#update}
   * @see {@link Fryr#append}
   * @fires window.onhashchange
   */
  function update(key, value, key_is_required, should_replace_value) {
    var hash = window.location.hash;

    // Ensure key exists in the hash
    if(hash.indexOf(key) !== -1) {
      var key_value = param(key);

      var regex_for_value = new RegExp(value, 'g');

      // If key_value contains the new value
      if(regex_for_value.test(key_value)) {

        // If key is required, swap it out
        if(key_is_required) {
          addValue(key, value, should_replace_value);

        } else {

          // If the value is blank, remove the original value from the key
          if(value === '') {
            removeValue(key, key_value);

          // Otherwise remove the vanilla value
          } else {
            if(key_value !== value) {
              removeValue(key, value);
            }

          }

          // If key's value is blank, remove it from hash
          if(param(key) === '') {
            removeKey(key);
          }

        }

      // key_value does not contain the new value
      } else {
        addValue(key, value, should_replace_value);

      }

    // Add key if it doesn't exist
    } else {

      if(window.location.hash) {
        window.location.hash += '&' + key + '=' + value;
      } else {
        // Use a question mark if first key
        window.location.hash = '?' + key + '=' + value;
      }

    }
  }

  /**
   * Callback with new params. Callback defined in initialization
   * @private
   * @fires hashChangeCallback
   */
  function privateHashChange() {
    var params = this.parse();
    this.callback.call(this, params);
  }

  /**
   * Call once to initialize filtering
   * @param {Function} hashChangeCallback - Called on every hashchange
   *   @param {Object} Updated params
   * @param {Object} [defaults={}] - Key/value pairs for values that should be added on init. Pass {} to skip defaults
   * @param {Boolean} [call_on_init=true] - Execute callback on initialization. Always true if defaults is supplied
   * @return {Fryr}
   */
  function Fryr(hashChangeCallback, defaults, call_on_init) {
    defaults = setDefault(defaults, {});
    call_on_init = setDefault(call_on_init, true);

    this.callback = hashChangeCallback;

    /**
     * Very important object holder
     * @type {Object}
     */
    this.params = {};

    window.addEventListener('hashchange', privateHashChange.bind(this));

    // Apply defaults (if present) to hash, which will file window.onhashchange
    if( Object.keys(defaults).length && window.location.hash === '' ) {
      this.merge(defaults, true);

    // Execute the callback on load
    } else if(call_on_init) {
      privateHashChange.call(this);

    }

    return this;
  }

  /**
   * Replace key/value if present in hash; add key/value if not present in hash
   * @param {String} key - Param key to query against
   * @param {String|Number} value - Value for param key
   * @param {Boolean} [key_is_required=false] - if the key is not required, it will be removed from the hash
   * @see {@link Fryr#append}
   */
  Fryr.prototype.update = function(key, value, key_is_required) {
    key_is_required = setDefault(key_is_required, false);
    update(key, value, key_is_required, true);
  };

  /**
   * Add value to key's value in a comma-delineated list if it's not present in hash
   * @param {String} key - Param key to query against
   * @param {String|Number} value - Value for param key
   * @see {@link Fryr#update}
   */
  Fryr.prototype.append = function(key, value) {
    update(key, value, false, false);
  };

  /**
   * Evaluate the hash
   * @return {Object} Key/value hash of the hash broken down by params
   */
  Fryr.prototype.parse = function() {
    var hash = window.location.hash;
    var params;

    // clear zombie keys and values
    this.params = {};

    if(window.location.hash && /\?/g.test(hash)) {
      params = hash.split('?')[1];
      params = params.split('&');

      // Separate params into key values
      for(var i = 0; i < params.length; i++) {
        var key_value = params[i].split('=');
        var key = key_value[0];
        var value = key_value[1];

        this.params[key] = value;
      }
    }

    return this.params;
  };

  /**
   * Change a JSON object into a string for the hash
   * @param {Object|String} obj - object to convert
   * @return {String|Boolean} For use in window.location.hash. Returns false if param is not object or string
   */
  Fryr.prototype.convert = function(obj) {
    if( obj.constructor === String ) {
      obj = JSON.parse(obj);
    }

    // Escape if we're not dealing with an object
    if( obj.constructor !== Object ) {
      return false;
    }

    var keys = Object.keys(obj);
    // Set start with a ?
    var new_hash = '?';

    // Loop through all keys in the obj
    for(var i = 0; i < keys.length; i++) {
      var key = keys[i];
      var value = obj[ key ];

      if( value.constructor === Array ) {
        value = value.join(',');
      }

      // On next key, if it isn't the first, precede with an ampersand
      if(new_hash !== '?') {
        new_hash += '&';
      }

      // Append key/value to new_hash
      new_hash += key + '=' + value;
    }

    return new_hash;
  };

  /**
   * Wipe out or selectively replace keys in params
   * @param {Object|String} obj - Query to replace
   * @param {Boolean} [replace_all=false] - Whether or not to blast existing params away or replace only changed keys
   * @fires window.onhashchange
   * @return {String} The new hash
   */
  Fryr.prototype.merge = function(obj, replace_all) {
    replace_all = setDefault(replace_all, false);

    // If it's a string, convert to an object
    if( obj.constructor === String ) {
      obj = JSON.parse(obj);
    }

    // Override or add key values from existing params and put them into the object
    if( !replace_all ) {
      var new_params = this.parse();

      var keys = Object.keys(new_params);

      for(var i = 0; i < keys.length; i++) {
        var key = keys[i];
        var value = new_params[ key ];

        if(!obj.hasOwnProperty(key)) {
          obj[key] = value;
        }
      }
    }

    // Change hash to string; if replace_all is false, original value is used
    var new_hash = this.convert(obj);

    window.location.hash = '#' + new_hash;

    return new_hash;
  };

  /**
   * Retrieve a key's value
   * @param {String} key - Param to target
   * @example
   * window.location.hash = '?color=blue'
   * fryr.param('color') // => 'blue'
   * @return {String} The value of the key
   */
  Fryr.prototype.param = function(key) {
    return param(key);
  };

  /**
   * Determine if param is blank or undefined
   * @param {String} key - Param to target
   * @return {Boolean}
   */
  Fryr.prototype.paramPresent = function(key) {
    var value = this.params[key];
    return (typeof value !== 'undefined' && value !== '');
  };

  /**
   * Destroy current initialization, unbind hashchange listener, and reset the hash to an empty state
   * @param {Boolean} [retain_hash=false] - Keep items in hash
   */
  Fryr.prototype.destroy = function(retain_hash){
    retain_hash = setDefault(retain_hash, false);

    window.removeEventListener('hashchange', privateHashChange);

    if(!retain_hash) {
      window.location.hash = '';
    }
  };

  return Fryr;

});
<|endoftext|>


<commit_before>var http = require('http')
, path = require('path')
, fs = require('fs')
, url = require('url')
, requireAgain = function(event,filename){
  var ext = path.extname(filename)
  , name = path.basename(filename,ext)
  if (require.cache[name]) delete require.cache[name]
  require(filename)
}
, requireAll = function(dir,callback){
  fs.readdir(dir,function(e,files){
    if (!e) files.forEach(function(filename,filenumber){
      requireAgain('rename',filename)
      if (filenumber===files.length-1) callback()
    })
  })
}
, router = function(req,res){
  var url = url.parse(req.url,true)
  , parts = url.pathname.split('/')
  , method = req.method.toLowerCase()
  if ((name = parts[0])) require.cache[name].method()
  else require.main.exports.method()
}
exports = function(port){
  var dir = path.dirname(require.main.filename)
  requireAll(dir,function(){
    fs.watch(dir,requireAgain)
    http.createServer(router).listen(port)
  })
}
<commit_msg>Pass route as arguments to module<commit_after>var http = require('http')
, path = require('path')
, fs = require('fs')
, url = require('url')
, requireAgain = function(event,filename){
  var ext = path.extname(filename)
  , name = path.basename(filename,ext)
  if (require.cache[name]) delete require.cache[name]
  require(filename)
}
, requireAll = function(dir,callback){
  fs.readdir(dir,function(e,files){
    if (!e) files.forEach(function(filename,filenumber){
      requireAgain('rename',filename)
      if (filenumber===files.length-1) callback()
    })
  })
}
, router = function(req,res){
  var urlObject = url.parse(req.url,true)
  , parts = urlObject.pathname.split('/')
  , method = req.method.toLowerCase()
  if (((name=parts[0]))&&(require.cache[name])) require.cache[name].method.apply(this,parts.slice(1))
  else require.main.exports.method.apply(this,parts)
}
exports = function(port){
  var dir = path.dirname(require.main.filename)
  requireAll(dir,function(){
    fs.watch(dir,requireAgain)
    http.createServer(router).listen(port)
  })
}
<|endoftext|>


<commit_before>var Neuvol;
var game;
var FPS = 60;
var maxScore=0;

var images = {};

var speed = function(fps){
	FPS = parseInt(fps);
}

var loadImages = function(sources, callback){
	var nb = 0;
	var loaded = 0;
	var imgs = {};
	for(var i in sources){
		nb++;
		imgs[i] = new Image();
		imgs[i].src = sources[i];
		imgs[i].onload = function(){
			loaded++;
			if(loaded == nb){
				callback(imgs);
			}
		}
	}
}

var Bird = function(json){
	this.x = 80;
	this.y = 250;
	this.width = 40;
	this.height = 30;

	this.alive = true;
	this.gravity = 0;
	this.velocity = 0.3;
	this.jump = -6;

	this.init(json);
}

Bird.prototype.init = function(json){
	for(var i in json){
		this[i] = json[i];
	}
}

Bird.prototype.flap = function(){
	this.gravity = this.jump;
}

Bird.prototype.update = function(){
	this.gravity += this.velocity;
	this.y += this.gravity;
}

Bird.prototype.isDead = function(height, pipes){
	if(this.y >= height || this.y + this.height <= 0){
		return true;
	}
	for(var i in pipes){
		if(!(
			this.x > pipes[i].x + pipes[i].width ||
			this.x + this.width < pipes[i].x ||
			this.y > pipes[i].y + pipes[i].height ||
			this.y + this.height < pipes[i].y
			)){
			return true;
	}
}
}

var Pipe = function(json){
	this.x = 0;
	this.y = 0;
	this.width = 50;
	this.height = 40;
	this.speed = 3;

	this.init(json);
}

Pipe.prototype.init = function(json){
	for(var i in json){
		this[i] = json[i];
	}
}

Pipe.prototype.update = function(){
	this.x -= this.speed;
}

Pipe.prototype.isOut = function(){
	if(this.x + this.width < 0){
		return true;
	}
}

var Game = function(){
	this.pipes = [];
	this.birds = [];
	this.score = 0;
	this.canvas = document.querySelector("#flappy");
	this.ctx = this.canvas.getContext("2d");
	this.width = this.canvas.width;
	this.height = this.canvas.height;
	this.spawnInterval = 90;
	this.interval = 0;
	this.gen = [];
	this.alives = 0;
	this.generation = 0;
	this.backgroundSpeed = 0.5;
	this.backgroundx = 0;
    this.maxScore = 0;
}

Game.prototype.start = function(){
	this.interval = 0;
	this.score = 0;
	this.pipes = [];
	this.birds = [];

	this.gen = Neuvol.nextGeneration();
	for(var i in this.gen){
		var b = new Bird();
		this.birds.push(b)
	}
	this.generation++;
	this.alives = this.birds.length;
}

Game.prototype.update = function(){
	this.backgroundx += this.backgroundSpeed;
	var nextHoll = 0;
	if(this.birds.length > 0){
		for(var i = 0; i < this.pipes.length; i+=2){
			if(this.pipes[i].x + this.pipes[i].width > this.birds[0].x){
				nextHoll = this.pipes[i].height/this.height;
				break;
			}
		}
	}

	for(var i in this.birds){
		if(this.birds[i].alive){

			var inputs = [
			this.birds[i].y / this.height,
			nextHoll
			];

			var res = this.gen[i].compute(inputs);
			if(res > 0.5){
				this.birds[i].flap();
			}

			this.birds[i].update();
			if(this.birds[i].isDead(this.height, this.pipes)){
				this.birds[i].alive = false;
				this.alives--;
				//console.log(this.alives);
				Neuvol.networkScore(this.gen[i], this.score);
				if(this.isItEnd()){
					this.start();
				}
			}
		}
	}

	var deletedPipes = [];
	for(var i in this.pipes){
		this.pipes[i].update();
		if(this.pipes[i].isOut()){
			deletedPipes.push(i);
		}
	}

	var deltaIndex = 0;
	for(var i in deletedPipes){
		this.pipes.splice(deletedPipes[i] - deltaIndex, 1);
		deltaIndex++;
	}

	if(this.interval == 0){
		var deltaBord = 50;
		var pipeHoll = 120;
		var hollPosition = Math.round(Math.random() * (this.height - deltaBord * 2 - pipeHoll)) +  deltaBord;
		this.pipes.push(new Pipe({x:this.width, y:0, height:hollPosition}));
		this.pipes.push(new Pipe({x:this.width, y:hollPosition+pipeHoll, height:this.height}));
	}

	this.interval++;
	if(this.interval == this.spawnInterval){
		this.interval = 0;
	}

	this.score++;
    this.maxScore = (this.score > this.maxScore) ? this.score : this.maxScore;
	var self = this;
	setTimeout(function(){
		self.update();
	}, 1000/FPS);

	this.display();
}

Game.prototype.isItEnd = function(){
	for(var i in this.birds){
		if(this.birds[i].alive){
			return false;
		}
	}
	return true;
}

Game.prototype.display = function(){
	this.ctx.clearRect(0, 0, this.width, this.height);
	for(var i = 0; i < Math.ceil(this.width / images.background.width) + 1; i++){
		this.ctx.drawImage(images.background, i * images.background.width - Math.floor(this.backgroundx%images.background.width), 0)
	}

	for(var i in this.pipes){
		if(i%2 == 0){
			this.ctx.drawImage(images.pipetop, this.pipes[i].x, this.pipes[i].y + this.pipes[i].height - images.pipetop.height, this.pipes[i].width, images.pipetop.height);
		}else{
			this.ctx.drawImage(images.pipebottom, this.pipes[i].x, this.pipes[i].y, this.pipes[i].width, images.pipetop.height);
		}
	}

	this.ctx.fillStyle = "#FFC600";
	this.ctx.strokeStyle = "#CE9E00";
	for(var i in this.birds){
		if(this.birds[i].alive){
			this.ctx.save();
 			this.ctx.translate(this.birds[i].x, this.birds[i].y);
 			this.ctx.translate(this.birds[i].width/2, this.birds[i].height/2);
 			this.ctx.rotate(Math.PI/2 * this.birds[i].gravity/20);
 			this.ctx.drawImage(images.bird, -this.birds[i].width, -this.birds[i].height/2, this.birds[i].width, this.birds[i].height);
 			this.ctx.restore();
		}
	}

	this.ctx.fillStyle = "white";
	this.ctx.font="20px Oswald, sans-serif";
	this.ctx.fillText("Score : "+ this.score, 10, 25);
	this.ctx.fillText("Max Score : "+this.maxScore, 10, 50);
	this.ctx.fillText("Generation : "+this.generation, 10, 75);
	this.ctx.fillText("Alive : "+this.alives+" / "+Neuvol.options.population, 10, 100);
}

window.onload = function(){
	var sprites = {
		bird:"./img/bird.png",
		background:"./img/background.png",
		pipetop:"./img/pipetop.png",
		pipebottom:"./img/pipebottom.png"
	}

	var start = function(){
		Neuvol = new Neuroevolution({
			population:50,
			network:[2, [2], 1],
		});
		game = new Game();
		game.start();
		setTimeout(function(){
			game.update();
		}, 1000/FPS);
	}

	loadImages(sprites, function(imgs){
		images = imgs;
		start();
	})

}
<commit_msg>Add vertically moving pipes<commit_after>var Neuvol;
var game;
var FPS = 60;
var maxScore=0;
var HOLE_HEIGHT = 120;

var images = {};

var speed = function(fps){
	FPS = parseInt(fps);
}

var loadImages = function(sources, callback){
	var nb = 0;
	var loaded = 0;
	var imgs = {};
	for(var i in sources){
		nb++;
		imgs[i] = new Image();
		imgs[i].src = sources[i];
		imgs[i].onload = function(){
			loaded++;
			if(loaded == nb){
				callback(imgs);
			}
		}
	}
}

var Bird = function(json){
	this.x = 80;
	this.y = 250;
	this.width = 40;
	this.height = 30;

	this.alive = true;
	this.gravity = 0;
	this.velocity = 0.3;
	this.jump = -6;

	this.init(json);
}

Bird.prototype.init = function(json){
	for(var i in json){
		this[i] = json[i];
	}
}

Bird.prototype.flap = function(){
	this.gravity = this.jump;
}

Bird.prototype.update = function(){
	this.gravity += this.velocity;
	this.y += this.gravity;
}

Bird.prototype.isDead = function(height, pipes){
	if(this.y >= height || this.y + this.height <= 0){
		return true;
	}
	for(var i in pipes){
		if(!(
			this.x > pipes[i].x + pipes[i].width ||
			this.x + this.width < pipes[i].x ||
			this.y > pipes[i].y + pipes[i].height ||
			this.y + this.height < pipes[i].y
			)){
			return true;
	}
}
}

var Pipe = function(json){
	this.x = 0;
	this.y = 0;
	this.width = 50;
	this.height = 40;
	this.speed = 3;
	this.verticalSpeed = 0;

	this.init(json);
}

Pipe.prototype.init = function(json){
	for(var i in json){
		this[i] = json[i];
	}
}

Pipe.prototype.update = function(){
	this.x -= this.speed;

	var pipeBounceBuffer = 10;
	if (this.isTopPipe()) {
		this.height += this.verticalSpeed;

		if (this.height < pipeBounceBuffer || this.height > (game.height - HOLE_HEIGHT - pipeBounceBuffer)) {
			this.verticalSpeed *= -1;
		}
	} else {
		this.y += this.verticalSpeed;

		if (this.y < (pipeBounceBuffer + HOLE_HEIGHT) || this.y > (game.height - pipeBounceBuffer) {
			this.verticalSpeed *= -1;
		}
	}
}

Pipe.prototype.isOut = function(){
	if(this.x + this.width < 0){
		return true;
	}
}

Pipe.prototype.isTopPipe = function(){
	return this.y === 0;
}

var Game = function(){
	this.pipes = [];
	this.birds = [];
	this.score = 0;
	this.canvas = document.querySelector("#flappy");
	this.ctx = this.canvas.getContext("2d");
	this.width = this.canvas.width;
	this.height = this.canvas.height;
	this.spawnInterval = 90;
	this.interval = 0;
	this.gen = [];
	this.alives = 0;
	this.generation = 0;
	this.backgroundSpeed = 0.5;
	this.backgroundx = 0;
    this.maxScore = 0;
}

Game.prototype.start = function(){
	this.interval = 0;
	this.score = 0;
	this.pipes = [];
	this.birds = [];

	this.gen = Neuvol.nextGeneration();
	for(var i in this.gen){
		var b = new Bird();
		this.birds.push(b)
	}
	this.generation++;
	this.alives = this.birds.length;
}

Game.prototype.update = function(){
	this.backgroundx += this.backgroundSpeed;
	var nextHoll = 0;
	if(this.birds.length > 0){
		for(var i = 0; i < this.pipes.length; i+=2){
			if(this.pipes[i].x + this.pipes[i].width > this.birds[0].x){
				nextHoll = this.pipes[i].height/this.height;
				break;
			}
		}
	}

	for(var i in this.birds){
		if(this.birds[i].alive){

			var inputs = [
			this.birds[i].y / this.height,
			nextHoll
			];

			var res = this.gen[i].compute(inputs);
			if(res > 0.5){
				this.birds[i].flap();
			}

			this.birds[i].update();
			if(this.birds[i].isDead(this.height, this.pipes)){
				this.birds[i].alive = false;
				this.alives--;
				//console.log(this.alives);
				Neuvol.networkScore(this.gen[i], this.score);
				if(this.isItEnd()){
					this.start();
				}
			}
		}
	}

	var deletedPipes = [];
	for(var i in this.pipes){
		this.pipes[i].update();
		if(this.pipes[i].isOut()){
			deletedPipes.push(i);
		}
	}

	var deltaIndex = 0;
	for(var i in deletedPipes){
		this.pipes.splice(deletedPipes[i] - deltaIndex, 1);
		deltaIndex++;
	}

	if(this.interval == 0){
		var deltaBord = 50;
		var pipeVerticalMoveSpeed = (Math.random() * 3);
		var hollPosition = Math.round(Math.random() * (this.height - deltaBord * 2 - HOLE_HEIGHT)) +  deltaBord;
		this.pipes.push(new Pipe({x:this.width, y:0, height:hollPosition, verticalSpeed: pipeVerticalMoveSpeed}));
		this.pipes.push(new Pipe({x:this.width, y:hollPosition+HOLE_HEIGHT, height:this.height, verticalSpeed: pipeVerticalMoveSpeed}));
	}

	this.interval++;
	if(this.interval == this.spawnInterval){
		this.interval = 0;
	}

	this.score++;
    this.maxScore = (this.score > this.maxScore) ? this.score : this.maxScore;
	var self = this;
	setTimeout(function(){
		self.update();
	}, 1000/FPS);

	this.display();
}

Game.prototype.isItEnd = function(){
	for(var i in this.birds){
		if(this.birds[i].alive){
			return false;
		}
	}
	return true;
}

Game.prototype.display = function(){
	this.ctx.clearRect(0, 0, this.width, this.height);
	for(var i = 0; i < Math.ceil(this.width / images.background.width) + 1; i++){
		this.ctx.drawImage(images.background, i * images.background.width - Math.floor(this.backgroundx%images.background.width), 0)
	}

	for(var i in this.pipes){
		if(i%2 == 0){
			this.ctx.drawImage(images.pipetop, this.pipes[i].x, this.pipes[i].y + this.pipes[i].height - images.pipetop.height, this.pipes[i].width, images.pipetop.height);
		}else{
			this.ctx.drawImage(images.pipebottom, this.pipes[i].x, this.pipes[i].y, this.pipes[i].width, images.pipetop.height);
		}
	}

	this.ctx.fillStyle = "#FFC600";
	this.ctx.strokeStyle = "#CE9E00";
	for(var i in this.birds){
		if(this.birds[i].alive){
			this.ctx.save();
 			this.ctx.translate(this.birds[i].x, this.birds[i].y);
 			this.ctx.translate(this.birds[i].width/2, this.birds[i].height/2);
 			this.ctx.rotate(Math.PI/2 * this.birds[i].gravity/20);
 			this.ctx.drawImage(images.bird, -this.birds[i].width, -this.birds[i].height/2, this.birds[i].width, this.birds[i].height);
 			this.ctx.restore();
		}
	}

	this.ctx.fillStyle = "white";
	this.ctx.font="20px Oswald, sans-serif";
	this.ctx.fillText("Score : "+ this.score, 10, 25);
	this.ctx.fillText("Max Score : "+this.maxScore, 10, 50);
	this.ctx.fillText("Generation : "+this.generation, 10, 75);
	this.ctx.fillText("Alive : "+this.alives+" / "+Neuvol.options.population, 10, 100);
}

window.onload = function(){
	var sprites = {
		bird:"./img/bird.png",
		background:"./img/background.png",
		pipetop:"./img/pipetop.png",
		pipebottom:"./img/pipebottom.png"
	}

	var start = function(){
		Neuvol = new Neuroevolution({
			population:50,
			network:[2, [2], 1],
		});
		game = new Game();
		game.start();
		setTimeout(function(){
			game.update();
		}, 1000/FPS);
	}

	loadImages(sprites, function(imgs){
		images = imgs;
		start();
	})

}
<|endoftext|>


<commit_before>var button = []; //stores the canvases
for(var i=1; i<10; i++) button[i] = document.getElementById('canvas'+i);

var ctx = []; //stores the context of the canvases
for(var i=1; i<10; i++) ctx[i] = button[i].getContext('2d');

var bDisabled = []; //stores the availability of the button
for(var i=1; i<10; i++) bDisabled[i] = false; //all buttons are enabled in the beginning

var isResult = false;
var content = [];

var xTurn = true; //X:true O:false

function loop(x)
{
    if(!bDisabled[x]){ //button does not currently contain X or O and therefore is enabled.
        bDisabled[x] = true; //button now contains something
        console.log("Button pressed.");
        content[x] = 'x';

        button[x].style.webkitTransform = "rotateY(180deg)";

        setTimeout(function(){
            ctx[x].lineWidth = 3;
            ctx[x].beginPath();
            ctx[x].moveTo(10, 10);
            ctx[x].lineTo(90, 90);
            ctx[x].moveTo(90, 10);
            ctx[x].lineTo(10, 90);
            ctx[x].stroke();
            ctx[x].closePath();
        }, 300);

    }
}<commit_msg>small refprmatting<commit_after>var button = []; //stores the canvases
for(var i=1; i<10; i++) button[i] = document.getElementById('canvas'+i);

var ctx = []; //stores the context of the canvases
for(var i=1; i<10; i++) ctx[i] = button[i].getContext('2d');

var bDisabled = []; //stores the availability of the button
for(var i=1; i<10; i++) bDisabled[i] = false; //all buttons are enabled in the beginning

var isResult = false;
var content = [];

var xTurn = true; //X:true O:false

function loop(x)
{
    if(!bDisabled[x]){ //button does not currently contain X or O and therefore is enabled.
        bDisabled[x] = true; //button now contains something
        //console.log("Button pressed.");

        button[x].style.webkitTransform = "rotateY(180deg)";

        content[x] = 'x';

        setTimeout(function(){
            ctx[x].lineWidth = 3;
            ctx[x].beginPath();
            ctx[x].moveTo(10, 10);
            ctx[x].lineTo(90, 90);
            ctx[x].moveTo(90, 10);
            ctx[x].lineTo(10, 90);
            ctx[x].stroke();
            ctx[x].closePath();
        }, 300);

    }
}<|endoftext|>