text: !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.fhlog=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
  'use strict';
  
  exports.green = function (str) {
    return str;
  };
  
  exports.yellow = function (str) {
    return str;
  };
  
  exports.red = function (str) {
    return str;
  };
  
  exports.magenta = function (str) {
    return str;
  };
  
  exports.green = function (str) {
    return str;
  };
  
  },{}],2:[function(_dereq_,module,exports){
  'use strict';
  
  module.exports = {
    'DBG': 0,
    'INF': 1,
    'WRN': 2,
    'ERR': 3
  };
  
  },{}],3:[function(_dereq_,module,exports){
  'use strict';
  
  var util = _dereq_('util')
    , _ = _dereq_('lodash')
    , transport = _dereq_('./transport')
    , LEVELS = _dereq_('./Levels')
    , meta = _dereq_('./Meta');
  
  // Enable colourisation - this isn't enabled for browsers
  var colours = _dereq_('colors/safe');
  
  
  /**
   * Get the level string for a log, e.g "INF", "DBG" etc.
   * Also adds colour to the when enabled.
   * @param  {Object} opts
   */
  function getLevelStr (opts) {
    var lvlStr = _.invert(LEVELS)[opts.level]
      , useColours = opts.colourise || true;
  
    if (useColours) {
      switch (opts.level) {
        case LEVELS.DBG:
          lvlStr = colours.magenta(lvlStr);
          break;
        case LEVELS.INF:
          lvlStr = colours.green(lvlStr);
          break;
        case LEVELS.WRN:
          lvlStr = colours.yellow(lvlStr);
          break;
        case LEVELS.ERR:
          lvlStr = colours.red(lvlStr);
          break;
      }
    }
  
    return lvlStr;
  }
  
  
  /**
   * @public
   * @constructor
   * Creates a log instance with data required to log a string.
   */
  function Log (opts, args) {
    args = Array.prototype.slice.call(args);
  
    var ts = Date.now()
      , lvlStr = getLevelStr(opts)
      , prefix = ''
      , name = opts.name;
  
    // Set text to be just the text user supplied
    this.text = util.format.apply(util, args);
  
    // Build log prefix
    prefix = util.format('%s %s %s: ', new Date(ts).toJSON(), lvlStr, name);
  
    // Normalise first arg to a include our string if necessary
    if (typeof args[0] === 'string') {
      args[0] = prefix + args[0];
    }
  
    // Set text to be just the text user supplied
    this.formattedText = util.format.apply(util, args);
  
    // Format the string so we can save it and output it correctly
    this.ts = ts;
    this.level = opts.level;
    this.name = name;
  }
  module.exports = Log;
  
  
  /**
   * Write the contents of this log to output transport
   * @param   {Boolean} silent
   * @return  {String}
   */
  Log.prototype.print = function (print) {
    if (print) {
      transport.log(this.level, this.formattedText);
    }
  
    return this.formattedText;
  };
  
  
  /**
   * Get the date that this log was created.
   * @return {String}
   */
  Log.prototype.getDate = function () {
    return new Date(this.ts).toJSON().substr(0, 10);
  };
  
  
  /**
   * Return a JSON object representing this log.
   * @return {Object}
   */
  Log.prototype.toJSON = function () {
    return {
      ts: this.ts,
      text: this.text,
      name: this.name,
      level: this.level,
      meta: meta.get()
    };
  };
  
  },{"./Levels":2,"./Meta":6,"./transport":10,"colors/safe":1,"lodash":20,"util":16}],4:[function(_dereq_,module,exports){
  'use strict';
  
  var Log = _dereq_('./Log')
    , persistence = _dereq_('./Persistence')
    , LEVELS = _dereq_('./Levels');
  
  /**
   * @constructor
   * Wrapper for the console object.
   * Should behave the same as console.METHOD
   * @param {String}    [name]    Name of this logger to include in logs.
   * @param {Number}    [level]   Level to use for calls to .log
   * @param {Boolean}   [upload]  Determines if logs are uploaded.
   * @param {Boolean}   [silent]  Flag indicating if we print to stdout or not.
   */
  function Logger (name, opts) {
    opts = opts || {};
  
    this._name = name || '';
    this._logLevel = opts.level || LEVELS.DBG;
    this._upload = opts.upload || false;
    this._silent = opts.silent || false;
    this._colourise = opts.colourise || true;
  }
  module.exports = Logger;
  
  Logger.prototype.LEVELS = LEVELS;
  Logger.LEVELS = LEVELS;
  
  
  /**
   * @private
   * Log output to stdout with format: "2014-06-26T16:42:11.139Z LoggerName:"
   * @param   {Number}  level
   * @param   {Array}   args
   * @return  {String}
   */
  Logger.prototype._log = function(level, args) {
    if (level < this.getLogLevel()) {
      // Don't log anything if the log level is set above the provided level
      return;
    }
  
    var l = new Log({
      colourise: this._colourise,
      level: level,
      name: this.getName()
    }, args);
  
    if (this._upload) {
      persistence.writeLog(l);
    }
  
    return l.print(!this.isSilent());
  };
  
  
  /**
   * @public
   * Toggle printing out logs to stdout.
   * @param {Boolean} silent
   */
  Logger.prototype.setSilent = function (silent) {
    this._silent = silent || false;
  };
  
  
  /**
   * @public
   * Determine if this logger is printing to stdout.
   * @returns {Boolean}
   */
  Logger.prototype.isSilent = function () {
    return this._silent;
  };
  
  
  /**
   * @public
   * Log a message at 'DEBUG' level
   * Log a string and return the string value of the provided log args.
   * This operates in the same manner as console.debug
   * @param [arguments] arguments The list of args to log.
   * @returns {String}
   */
  Logger.prototype.debug = function () {
    return this._log(LEVELS.DBG, arguments);
  };
  
  
  /**
   * @public
   * Log a message at 'INFO' level
   * Log a string and return the string value of the provided log args.
   * This operates in the same manner as console.info
   * @param [arguments] arguments The list of args to log.
   * @returns {String}
   */
  Logger.prototype.info = function () {
    return this._log(LEVELS.INF, arguments);
  };
  
  
  /**
   * @public
   * Log a message at 'WARN' level
   * Log a string and return the string value of the provided log args.
   * This operates in the same manner as console.warn
   * @param [arguments] arguments The list of args to log.
   * @returns {String}
   */
  Logger.prototype.warn = function () {
    return this._log(LEVELS.WRN, arguments);
  };
  
  
  /**
   * @public
   * Log a message at 'ERROR' level
   * Log a string and return the string value of the provided log args.
   * This operates in the same manner as console.error
   * @param [arguments] arguments The list of args to log.
   * @returns {String}
   */
  Logger.prototype.err = function () {
    return this._log(LEVELS.ERR, arguments);
  };
  
  
  /**
   * @public
   * Shim for the info Logger function.
   */
  Logger.prototype.i = Logger.prototype.info;
  
  
  /**
   * @public
   * Shim for the error Logger function.
   */
  Logger.prototype.e = Logger.prototype.err;
  
  
  /**
   * @public
   * Shim for the warn Logger function.
   */
  Logger.prototype.w = Logger.prototype.warn;
  
  
  /**
   * @public
   * Shim for the debug Logger function.
   */
  Logger.prototype.d = Logger.prototype.debug;
  
  
  /**
   * @public
   * Log a message at 'ERROR' level
   * Log a string and return the string value of the provided log args.
   * This operates in the same manner as console.error
   * @param [arguments] arguments The list of args to log.
   * @returns {String}
   */
  Logger.prototype.error = Logger.prototype.err;
  
  
  /**
   * @public
   * Set the level of this logger for calls to the .log instance method.
   * @param {Number} lvl
   */
  Logger.prototype.setLogLevel = function (lvl) {
    this._logLevel = lvl;
  };
  
  
  /**
   * @public
   * Get the level of this logger used by calls to the .log instance method.
   * @returns {Number}
   */
  Logger.prototype.getLogLevel = function () {
    return this._logLevel;
  };
  
  
  /**
   * @public
   * Get the name of this logger.
   * @returns {String}
   */
  Logger.prototype.getName = function () {
    return this._name;
  };
  
  
  /**
   * @public
   * Set the name of this logger. It would be very unusual to use this.
   * @param {String} name
   */
  Logger.prototype.setName = function(name) {
    this._name = name;
  };
  
  },{"./Levels":2,"./Log":3,"./Persistence":7}],5:[function(_dereq_,module,exports){
  'use strict';
  
  var Logger = _dereq_('./Logger')
    , LEVELS = _dereq_('./Levels')
    , persistence = _dereq_('./Persistence')
    , meta = _dereq_('./Meta')
    , _ = _dereq_('lodash');
  
  var loggers = {}    // Loggers created. Same name loggers exist only once.
    , defaults = {};  // Defaults to apply to each logger at creation
  
  
  /**
   * @public
   * The Log levels available for use.
   * @type {Object}
   */
  exports.LEVELS = LEVELS;
  
  
  /**
   * @public
   * Metadata interface
   * @type {Object}
   */
  exports.meta = meta;
  
  
  /**
   * @public
   * Set the global log level for all log instances.
   * @param {[type]} level [description]
   */
  exports.setGlobalLevel = function (level) {
    for (var i in loggers) {
      loggers[i].setLogLevel(level);
    }
  };
  
  
  /**
   * @public
   * Initialise the log library.
   * @param  {Object}   opts
   * @param  {Function} callback
   */
  exports.init = function (opts, callback) {
    // Ensure metadata is set for each log
    meta.set(opts.meta || {});
  
    persistence.init(opts, callback);
  };
  
  
  /**
   * Set a default property to apply to all loggers
   * @param {String} name The property to create a default for
   * @param {String} val  The default value
   */
  exports.setDefault = function (name, val) {
    defaults[name] = val;
  };
  
  
  /**
   * Forces all loggers into silent mode.
   */
  exports.silenceIsGolden = exports.silenceAll = function () {
    _.each(loggers, function (l) {
      l.setSilent(true);
    });
  };
  
  
  /**
   * Forces all loggers out of silent mode.
   */
  exports.permissionToSpeakGranted = exports.unsilenceAll = function () {
    _.each(loggers, function (l) {
      l.setSilent(false);
    });
  };
  
  
  /**
   * @public
   * Get a named logger instance creating it if it doesn't already exist.
   * @param   {String}    [name]
   * @param   {Object}    [opts]
   * @returns {Logger}
   */
  exports.getLogger = exports.get = function (name, opts) {
    name = name || '';
    opts = opts || {};
  
    if (loggers[name]) {
      return loggers[name];
    } else {
      // Get a logger with user opts and defaults, current opts take priority
      loggers[name] = new Logger(name, _.assign(defaults, opts));
  
      return loggers[name];
    }
  };
  
  // Register as an Angular module if possible
  if (typeof window !== 'undefined' && window.angular && window.angular.module) {
    angular.module('fhlog', [])
      .service('fhlog', function () {
        // Return the service with the properties of the LoggerFactory appended
        return _.assign(this, exports);
      });
  }
  
  },{"./Levels":2,"./Logger":4,"./Meta":6,"./Persistence":7,"lodash":20}],6:[function(_dereq_,module,exports){
  'use strict';
  
  var meta = {};
  
  /**
   * Checks that metadata supplied is the correct format.
   * @param  {Object} m
   */
  function verifyMeta (m) {
    if (typeof m !== 'object') {
      throw new Error('Meta for logs must be a serialisable object.');
    }
  
    try {
      JSON.stringify(m);
    } catch (e) {
      throw new Error('Meta for logs must be a serialisable object.');
    }
  }
  
  
  /**
   * Replace the entire meta object with an object.
   * @param  {Object} m
   */
  function replace (m) {
    verifyMeta(m);
  
    meta = m;
  }
  
  
  /**
   * Remove a key from the metadata.
   * @param  {String} key Key to remove from meta object
   * @return {Bool}       Success or failure flag
   */
  function remove(key) {
    return delete meta[key];
  }
  
  
  /**
   * Get the stored metadata
   * @return {Object}
   */
  function get () {
    return meta;
  }
  
  
  /**
   * Set the stored metadata.
   * This must be a serialisable JSON object
   * @param {Object} m
   */
  function set (key, val) {
    meta[key] = val;
  }
  
  module.exports = {
    replace: replace,
    remove: remove,
    get: get,
    set: set
  };
  
  },{}],7:[function(_dereq_,module,exports){
  'use strict';
  
  var safejson = _dereq_('safejson')
    , async = _dereq_('async')
    , path = _dereq_('path')
    , fs = _dereq_('./fileSystem')
    , _ = _dereq_('lodash');
  
  
  // Priority based queue to store log file ops.
  // Writes are highest priority, we don't want to lose logs!
  var opQ = async.priorityQueue(runQueueTask, 1);
  
  // Function that must be set to upload logs to a remote endpoint
  var uploadFn = null;
  
  // Tracks if this component has been initialisd
  var initialised = false;
  
  var LOG_DIR = './fhlogs'
    , FILE_EXT = '.txt'
    , TASK_PRIORITY = {
      WRITE: 1,
      UPLOAD: 2,
    }
    , DEFAULT_STORAGE_QUOTA = 25 * Math.pow(1024, 3) // Max log storage is 25MB
    , MAX_FILE_SIZE = 10 * Math.pow(1024, 2); // Max file size is 10KB
  
  
  function runQueueTask (task, callback) {
    // TODO: Handle errors passed to the callback
    task.fn(callback);
  }
  
  
  /**
   * Get a list of all the current log files
   * @param  {Function} callback
   */
  function getLogFiles (callback) {
    fs.readdir(LOG_DIR, callback);
  }
  
  
  /**
   * Get the name of the most recent log file
   * @param  {Array}    files
   * @param  {Function} callback
   */
  function getOldestFilename (callback) {
    getLogFiles(function (err, files) {
      if (err) {
        callback(err, null);
      } else if (!files || files.length === 0) {
        return callback(null, Date.now().toString().concat(FILE_EXT));
      } else {
        var file = _.min(files, function (f) {
          // Remove extension to get just the timestamp
          var ts = f.name.replace(FILE_EXT, '');
  
          return parseInt(ts, 10);
        });
  
        callback(null, file.name);
      }
    });
  }
  
  
  /**
   * Get the name of the most recent log file
   * @param  {Array}    files
   * @param  {Function} callback
   */
  function getMostRecentFilename (callback) {
    getLogFiles(function (err, files) {
      if (err) {
        callback(err, null);
      } else if (!files || files.length === 0) {
        return callback(null, Date.now().toString().concat(FILE_EXT));
      } else {
        var file = _.max(files, function (f) {
          var n = (f && typeof f.name === 'string') ? f.name : f;
  
          // Remove extension to get just the timestamp
          var ts = n.replace(FILE_EXT, '');
  
          return parseInt(ts, 10);
        });
  
        var n = (file && typeof file.name === 'string') ? file.name : file;
  
        callback(null, n);
      }
    });
  }
  
  
  /**
   * Determine the file to write the current log file to
   * @param  {String}   name
   * @param  {Function} callback
   */
  function getRequiredFilename (name, callback) {
    var filepath = path.join(LOG_DIR, name);
  
    function getStats () {
  
      fs.stat(filepath, function (err, stats) {
        if (err) {
          callback(err, null);
        } else if (stats && stats.size >= MAX_FILE_SIZE) {
          createFile();
        } else {
          callback(null, name);
        }
      });
    }
  
    function createFile () {
      fs.writeFile(filepath, '[]', function (err) {
        if (err) {
          callback(err, null);
        } else {
          callback(null, name);
        }
      });
    }
  
    fs.exists(filepath, function (exists) {
      if (exists) {
        getStats();
      } else {
        createFile();
      }
    });
  }
  
  
  /**
   * Generates a function that will perform logic required
   * to update a log file with a new log entry.
   * @param  {Log} log [description]
   */
  function getWriteFunction(log) {
    return function writeLogFile (name, qcb) {
      var dir = path.join(LOG_DIR, name);
  
      function readFile (cb) {
        fs.readFile(dir, cb);
      }
  
      function updateLogs (logs, cb) {
        logs.push(log.toJSON());
        cb(null, logs);
      }
  
      function writeFile (str, cb) {
        fs.writeFile(dir, str, cb);
      }
  
      async.waterfall([
        readFile,
        safejson.parse,
        updateLogs,
        safejson.stringify,
        writeFile
      ], qcb);
    };
  }
  
  
  /**
   * Read a log file with the given name
   * @param  {String}   name
   * @param  {Function} callback
   */
  function getLogsObject (name, callback) {
    fs.readFile(path.join(LOG_DIR, name), function (err, data) {
      if (err) {
        return callback(err, null);
      }
  
      safejson.parse(data, function (err, logArray) {
        if (err) {
          return callback(err, null);
        }
  
        callback(null, {
          logs: logArray
        });
      });
    });
  }
  
  
  /**
   * Delete a log file with the given name
   * @param  {String}   name
   * @param  {Function} callback
   */
  function deleteFile(name, callback) {
    fs.unlink(path.join(LOG_DIR, name), callback);
  }
  
  
  /**
   * Initialise this component for uploads.
   * @param  {Object}   opts
   * @param  {Function} callback
   */
  exports.init = function (opts, callback) {
    var quota = opts.stroageQuota || DEFAULT_STORAGE_QUOTA;
    uploadFn = opts.uploadFn || null;
  
    function afterInit (err) {
      if (err) {
        return callback(err, null);
      }
  
      initialised = true;
  
      fs.exists(LOG_DIR, function (exists) {
        if (exists) {
          return callback(null, null);
        }
  
        fs.mkdir(LOG_DIR, callback);
      });
    }
  
    if (fs.init) {
      fs.init(quota, afterInit);
    } else {
      afterInit();
    }
  };
  
  
  /**
   * Write a log to storage for uploading later.
   * @param  {Log} log
   * @param  {Function} callback
   */
  exports.writeLog = function (log, callback) {
    if (!initialised) {
      if (callback) {
        return callback('Cannot write log to storage. The file system never ' +
          ' initialised.', null);
      } else {
        return console.log('fhlog: Cannot write logs as FileSystem' +
          ' wasn\'t initialised');
      }
    }
  
    // TODO: Idea. Maybe queue Log objects and do this write on an interval?
    // Basically write in batches every second to avoid to many I/O ops
  
    function writeOp (qcb) {
      async.waterfall([
        getMostRecentFilename,
        getRequiredFilename,
        getWriteFunction(log)
      ], qcb);
    }
  
    // Queue this operation with the highest priority
    opQ.push({
      fn: writeOp
    }, TASK_PRIORITY.WRITE, callback);
  };
  
  
  /**
   * Upload the stored logs, using a FIFO strategy.
   * @param {Function} callback
   */
  exports.uploadLogs = function (callback) {
  
    function uploadOp (qcb) {
      async.waterfall([
        getOldestFilename,
        getLogsObject,
        safejson.stringify,
        uploadFn,
        getOldestFilename,
        deleteFile
      ], qcb);
    }
  
    opQ.push({
      fn: uploadOp
    }, TASK_PRIORITY.UPLOAD, callback);
  };
  
  },{"./fileSystem":8,"async":11,"lodash":20,"path":13,"safejson":21}],8:[function(_dereq_,module,exports){
  'use strict';
  
  module.exports = _dereq_('html5-fs');
  
  },{"html5-fs":17}],9:[function(_dereq_,module,exports){
  'use strict';
  
  var LEVELS = _dereq_('../Levels');
  
  /**
   * Logs output using the browser's console object.
   * @private
   * @param {Number} level
   * @param {String} str
   */
  module.exports = function (level, str) {
    var logFn = null;
  
    switch (level) {
      case LEVELS.DBG:
        logFn = console.debug || console.log;
        break;
      case LEVELS.INF:
        logFn = console.info || console.log;
        break;
      case LEVELS.WRN:
        logFn = console.warn || console.log;
        break;
      case LEVELS.ERR:
        logFn = console.error || console.log;
        break;
      default:
        logFn = console.log;
        break;
    }
  
    logFn.call(console, str);
  };
  
  },{"../Levels":2}],10:[function(_dereq_,module,exports){
  'use strict';
  
  
  exports.transports = {
    'console': _dereq_('./console')
  };
  
  // Transports to use, default inclues console
  var activeTransports = [exports.transports.console];
  
  /**
   * Log the provided log to the active transports.
   * @public
   * @param {Number} level
   * @param {String} str
   */
  exports.log = function (level, str) {
    for (var i in activeTransports) {
      activeTransports[i](level, str);
    }
  };
  
  },{"./console":9}],11:[function(_dereq_,module,exports){
  (function (process){
  /*!
   * async
   * https://github.com/caolan/async
   *
   * Copyright 2010-2014 Caolan McMahon
   * Released under the MIT license
   */
  /*jshint onevar: false, indent:4 */
  /*global setImmediate: false, setTimeout: false, console: false */
  (function () {
  
      var async = {};
  
      // global on the server, window in the browser
      var root, previous_async;
  
      root = this;
      if (root != null) {
        previous_async = root.async;
      }
  
      async.noConflict = function () {
          root.async = previous_async;
          return async;
      };
  
      function only_once(fn) {
          var called = false;
          return function() {
              if (called) throw new Error("Callback was already called.");
              called = true;
              fn.apply(root, arguments);
          }
      }
  
      //// cross-browser compatiblity functions ////
  
      var _toString = Object.prototype.toString;
  
      var _isArray = Array.isArray || function (obj) {
          return _toString.call(obj) === '[object Array]';
      };
  
      var _each = function (arr, iterator) {
          if (arr.forEach) {
              return arr.forEach(iterator);
          }
          for (var i = 0; i < arr.length; i += 1) {
              iterator(arr[i], i, arr);
          }
      };
  
      var _map = function (arr, iterator) {
          if (arr.map) {
              return arr.map(iterator);
          }
          var results = [];
          _each(arr, function (x, i, a) {
              results.push(iterator(x, i, a));
          });
          return results;
      };
  
      var _reduce = function (arr, iterator, memo) {
          if (arr.reduce) {
              return arr.reduce(iterator, memo);
          }
          _each(arr, function (x, i, a) {
              memo = iterator(memo, x, i, a);
          });
          return memo;
      };
  
      var _keys = function (obj) {
          if (Object.keys) {
              return Object.keys(obj);
          }
          var keys = [];
          for (var k in obj) {
              if (obj.hasOwnProperty(k)) {
                  keys.push(k);
              }
          }
          return keys;
      };
  
      //// exported async module functions ////
  
      //// nextTick implementation with browser-compatible fallback ////
      if (typeof process === 'undefined' || !(process.nextTick)) {
          if (typeof setImmediate === 'function') {
              async.nextTick = function (fn) {
                  // not a direct alias for IE10 compatibility
                  setImmediate(fn);
              };
              async.setImmediate = async.nextTick;
          }
          else {
              async.nextTick = function (fn) {
                  setTimeout(fn, 0);
              };
              async.setImmediate = async.nextTick;
          }
      }
      else {
          async.nextTick = process.nextTick;
          if (typeof setImmediate !== 'undefined') {
              async.setImmediate = function (fn) {
                // not a direct alias for IE10 compatibility
                setImmediate(fn);
              };
          }
          else {
              async.setImmediate = async.nextTick;
          }
      }
  
      async.each = function (arr, iterator, callback) {
          callback = callback || function () {};
          if (!arr.length) {
              return callback();
          }
          var completed = 0;
          _each(arr, function (x) {
              iterator(x, only_once(done) );
          });
          function done(err) {
            if (err) {
                callback(err);
                callback = function () {};
            }
            else {
                completed += 1;
                if (completed >= arr.length) {
                    callback();
                }
            }
          }
      };
      async.forEach = async.each;
  
      async.eachSeries = function (arr, iterator, callback) {
          callback = callback || function () {};
          if (!arr.length) {
              return callback();
          }
          var completed = 0;
          var iterate = function () {
              iterator(arr[completed], function (err) {
                  if (err) {
                      callback(err);
                      callback = function () {};
                  }
                  else {
                      completed += 1;
                      if (completed >= arr.length) {
                          callback();
                      }
                      else {
                          iterate();
                      }
                  }
              });
          };
          iterate();
      };
      async.forEachSeries = async.eachSeries;
  
      async.eachLimit = function (arr, limit, iterator, callback) {
          var fn = _eachLimit(limit);
          fn.apply(null, [arr, iterator, callback]);
      };
      async.forEachLimit = async.eachLimit;
  
      var _eachLimit = function (limit) {
  
          return function (arr, iterator, callback) {
              callback = callback || function () {};
              if (!arr.length || limit <= 0) {
                  return callback();
              }
              var completed = 0;
              var started = 0;
              var running = 0;
  
              (function replenish () {
                  if (completed >= arr.length) {
                      return callback();
                  }
  
                  while (running < limit && started < arr.length) {
                      started += 1;
                      running += 1;
                      iterator(arr[started - 1], function (err) {
                          if (err) {
                              callback(err);
                              callback = function () {};
                          }
                          else {
                              completed += 1;
                              running -= 1;
                              if (completed >= arr.length) {
                                  callback();
                              }
                              else {
                                  replenish();
                              }
                          }
                      });
                  }
              })();
          };
      };
  
  
      var doParallel = function (fn) {
          return function () {
              var args = Array.prototype.slice.call(arguments);
              return fn.apply(null, [async.each].concat(args));
          };
      };
      var doParallelLimit = function(limit, fn) {
          return function () {
              var args = Array.prototype.slice.call(arguments);
              return fn.apply(null, [_eachLimit(limit)].concat(args));
          };
      };
      var doSeries = function (fn) {
          return function () {
              var args = Array.prototype.slice.call(arguments);
              return fn.apply(null, [async.eachSeries].concat(args));
          };
      };
  
  
      var _asyncMap = function (eachfn, arr, iterator, callback) {
          arr = _map(arr, function (x, i) {
              return {index: i, value: x};
          });
          if (!callback) {
              eachfn(arr, function (x, callback) {
                  iterator(x.value, function (err) {
                      callback(err);
                  });
              });
          } else {
              var results = [];
              eachfn(arr, function (x, callback) {
                  iterator(x.value, function (err, v) {
                      results[x.index] = v;
                      callback(err);
                  });
              }, function (err) {
                  callback(err, results);
              });
          }
      };
      async.map = doParallel(_asyncMap);
      async.mapSeries = doSeries(_asyncMap);
      async.mapLimit = function (arr, limit, iterator, callback) {
          return _mapLimit(limit)(arr, iterator, callback);
      };
  
      var _mapLimit = function(limit) {
          return doParallelLimit(limit, _asyncMap);
      };
  
      // reduce only has a series version, as doing reduce in parallel won't
      // work in many situations.
      async.reduce = function (arr, memo, iterator, callback) {
          async.eachSeries(arr, function (x, callback) {
              iterator(memo, x, function (err, v) {
                  memo = v;
                  callback(err);
              });
          }, function (err) {
              callback(err, memo);
          });
      };
      // inject alias
      async.inject = async.reduce;
      // foldl alias
      async.foldl = async.reduce;
  
      async.reduceRight = function (arr, memo, iterator, callback) {
          var reversed = _map(arr, function (x) {
              return x;
          }).reverse();
          async.reduce(reversed, memo, iterator, callback);
      };
      // foldr alias
      async.foldr = async.reduceRight;
  
      var _filter = function (eachfn, arr, iterator, callback) {
          var results = [];
          arr = _map(arr, function (x, i) {
              return {index: i, value: x};
          });
          eachfn(arr, function (x, callback) {
              iterator(x.value, function (v) {
                  if (v) {
                      results.push(x);
                  }
                  callback();
              });
          }, function (err) {
              callback(_map(results.sort(function (a, b) {
                  return a.index - b.index;
              }), function (x) {
                  return x.value;
              }));
          });
      };
      async.filter = doParallel(_filter);
      async.filterSeries = doSeries(_filter);
      // select alias
      async.select = async.filter;
      async.selectSeries = async.filterSeries;
  
      var _reject = function (eachfn, arr, iterator, callback) {
          var results = [];
          arr = _map(arr, function (x, i) {
              return {index: i, value: x};
          });
          eachfn(arr, function (x, callback) {
              iterator(x.value, function (v) {
                  if (!v) {
                      results.push(x);
                  }
                  callback();
              });
          }, function (err) {
              callback(_map(results.sort(function (a, b) {
                  return a.index - b.index;
              }), function (x) {
                  return x.value;
              }));
          });
      };
      async.reject = doParallel(_reject);
      async.rejectSeries = doSeries(_reject);
  
      var _detect = function (eachfn, arr, iterator, main_callback) {
          eachfn(arr, function (x, callback) {
              iterator(x, function (result) {
                  if (result) {
                      main_callback(x);
                      main_callback = function () {};
                  }
                  else {
                      callback();
                  }
              });
          }, function (err) {
              main_callback();
          });
      };
      async.detect = doParallel(_detect);
      async.detectSeries = doSeries(_detect);
  
      async.some = function (arr, iterator, main_callback) {
          async.each(arr, function (x, callback) {
              iterator(x, function (v) {
                  if (v) {
                      main_callback(true);
                      main_callback = function () {};
                  }
                  callback();
              });
          }, function (err) {
              main_callback(false);
          });
      };
      // any alias
      async.any = async.some;
  
      async.every = function (arr, iterator, main_callback) {
          async.each(arr, function (x, callback) {
              iterator(x, function (v) {
                  if (!v) {
                      main_callback(false);
                      main_callback = function () {};
                  }
                  callback();
              });
          }, function (err) {
              main_callback(true);
          });
      };
      // all alias
      async.all = async.every;
  
      async.sortBy = function (arr, iterator, callback) {
          async.map(arr, function (x, callback) {
              iterator(x, function (err, criteria) {
                  if (err) {
                      callback(err);
                  }
                  else {
                      callback(null, {value: x, criteria: criteria});
                  }
              });
          }, function (err, results) {
              if (err) {
                  return callback(err);
              }
              else {
                  var fn = function (left, right) {
                      var a = left.criteria, b = right.criteria;
                      return a < b ? -1 : a > b ? 1 : 0;
                  };
                  callback(null, _map(results.sort(fn), function (x) {
                      return x.value;
                  }));
              }
          });
      };
  
      async.auto = function (tasks, callback) {
          callback = callback || function () {};
          var keys = _keys(tasks);
          var remainingTasks = keys.length
          if (!remainingTasks) {
              return callback();
          }
  
          var results = {};
  
          var listeners = [];
          var addListener = function (fn) {
              listeners.unshift(fn);
          };
          var removeListener = function (fn) {
              for (var i = 0; i < listeners.length; i += 1) {
                  if (listeners[i] === fn) {
                      listeners.splice(i, 1);
                      return;
                  }
              }
          };
          var taskComplete = function () {
              remainingTasks--
              _each(listeners.slice(0), function (fn) {
                  fn();
              });
          };
  
          addListener(function () {
              if (!remainingTasks) {
                  var theCallback = callback;
                  // prevent final callback from calling itself if it errors
                  callback = function () {};
  
                  theCallback(null, results);
              }
          });
  
          _each(keys, function (k) {
              var task = _isArray(tasks[k]) ? tasks[k]: [tasks[k]];
              var taskCallback = function (err) {
                  var args = Array.prototype.slice.call(arguments, 1);
                  if (args.length <= 1) {
                      args = args[0];
                  }
                  if (err) {
                      var safeResults = {};
                      _each(_keys(results), function(rkey) {
                          safeResults[rkey] = results[rkey];
                      });
                      safeResults[k] = args;
                      callback(err, safeResults);
                      // stop subsequent errors hitting callback multiple times
                      callback = function () {};
                  }
                  else {
                      results[k] = args;
                      async.setImmediate(taskComplete);
                  }
              };
              var requires = task.slice(0, Math.abs(task.length - 1)) || [];
              var ready = function () {
                  return _reduce(requires, function (a, x) {
                      return (a && results.hasOwnProperty(x));
                  }, true) && !results.hasOwnProperty(k);
              };
              if (ready()) {
                  task[task.length - 1](taskCallback, results);
              }
              else {
                  var listener = function () {
                      if (ready()) {
                          removeListener(listener);
                          task[task.length - 1](taskCallback, results);
                      }
                  };
                  addListener(listener);
              }
          });
      };
  
      async.retry = function(times, task, callback) {
          var DEFAULT_TIMES = 5;
          var attempts = [];
          // Use defaults if times not passed
          if (typeof times === 'function') {
              callback = task;
              task = times;
              times = DEFAULT_TIMES;
          }
          // Make sure times is a number
          times = parseInt(times, 10) || DEFAULT_TIMES;
          var wrappedTask = function(wrappedCallback, wrappedResults) {
              var retryAttempt = function(task, finalAttempt) {
                  return function(seriesCallback) {
                      task(function(err, result){
                          seriesCallback(!err || finalAttempt, {err: err, result: result});
                      }, wrappedResults);
                  };
              };
              while (times) {
                  attempts.push(retryAttempt(task, !(times-=1)));
              }
              async.series(attempts, function(done, data){
                  data = data[data.length - 1];
                  (wrappedCallback || callback)(data.err, data.result);
              });
          }
          // If a callback is passed, run this as a controll flow
          return callback ? wrappedTask() : wrappedTask
      };
  
      async.waterfall = function (tasks, callback) {
          callback = callback || function () {};
          if (!_isArray(tasks)) {
            var err = new Error('First argument to waterfall must be an array of functions');
            return callback(err);
          }
          if (!tasks.length) {
              return callback();
          }
          var wrapIterator = function (iterator) {
              return function (err) {
                  if (err) {
                      callback.apply(null, arguments);
                      callback = function () {};
                  }
                  else {
                      var args = Array.prototype.slice.call(arguments, 1);
                      var next = iterator.next();
                      if (next) {
                          args.push(wrapIterator(next));
                      }
                      else {
                          args.push(callback);
                      }
                      async.setImmediate(function () {
                          iterator.apply(null, args);
                      });
                  }
              };
          };
          wrapIterator(async.iterator(tasks))();
      };
  
      var _parallel = function(eachfn, tasks, callback) {
          callback = callback || function () {};
          if (_isArray(tasks)) {
              eachfn.map(tasks, function (fn, callback) {
                  if (fn) {
                      fn(function (err) {
                          var args = Array.prototype.slice.call(arguments, 1);
                          if (args.length <= 1) {
                              args = args[0];
                          }
                          callback.call(null, err, args);
                      });
                  }
              }, callback);
          }
          else {
              var results = {};
              eachfn.each(_keys(tasks), function (k, callback) {
                  tasks[k](function (err) {
                      var args = Array.prototype.slice.call(arguments, 1);
                      if (args.length <= 1) {
                          args = args[0];
                      }
                      results[k] = args;
                      callback(err);
                  });
              }, function (err) {
                  callback(err, results);
              });
          }
      };
  
      async.parallel = function (tasks, callback) {
          _parallel({ map: async.map, each: async.each }, tasks, callback);
      };
  
      async.parallelLimit = function(tasks, limit, callback) {
          _parallel({ map: _mapLimit(limit), each: _eachLimit(limit) }, tasks, callback);
      };
  
      async.series = function (tasks, callback) {
          callback = callback || function () {};
          if (_isArray(tasks)) {
              async.mapSeries(tasks, function (fn, callback) {
                  if (fn) {
                      fn(function (err) {
                          var args = Array.prototype.slice.call(arguments, 1);
                          if (args.length <= 1) {
                              args = args[0];
                          }
                          callback.call(null, err, args);
                      });
                  }
              }, callback);
          }
          else {
              var results = {};
              async.eachSeries(_keys(tasks), function (k, callback) {
                  tasks[k](function (err) {
                      var args = Array.prototype.slice.call(arguments, 1);
                      if (args.length <= 1) {
                          args = args[0];
                      }
                      results[k] = args;
                      callback(err);
                  });
              }, function (err) {
                  callback(err, results);
              });
          }
      };
  
      async.iterator = function (tasks) {
          var makeCallback = function (index) {
              var fn = function () {
                  if (tasks.length) {
                      tasks[index].apply(null, arguments);
                  }
                  return fn.next();
              };
              fn.next = function () {
                  return (index < tasks.length - 1) ? makeCallback(index + 1): null;
              };
              return fn;
          };
          return makeCallback(0);
      };
  
      async.apply = function (fn) {
          var args = Array.prototype.slice.call(arguments, 1);
          return function () {
              return fn.apply(
                  null, args.concat(Array.prototype.slice.call(arguments))
              );
          };
      };
  
      var _concat = function (eachfn, arr, fn, callback) {
          var r = [];
          eachfn(arr, function (x, cb) {
              fn(x, function (err, y) {
                  r = r.concat(y || []);
                  cb(err);
              });
          }, function (err) {
              callback(err, r);
          });
      };
      async.concat = doParallel(_concat);
      async.concatSeries = doSeries(_concat);
  
      async.whilst = function (test, iterator, callback) {
          if (test()) {
              iterator(function (err) {
                  if (err) {
                      return callback(err);
                  }
                  async.whilst(test, iterator, callback);
              });
          }
          else {
              callback();
          }
      };
  
      async.doWhilst = function (iterator, test, callback) {
          iterator(function (err) {
              if (err) {
                  return callback(err);
              }
              var args = Array.prototype.slice.call(arguments, 1);
              if (test.apply(null, args)) {
                  async.doWhilst(iterator, test, callback);
              }
              else {
                  callback();
              }
          });
      };
  
      async.until = function (test, iterator, callback) {
          if (!test()) {
              iterator(function (err) {
                  if (err) {
                      return callback(err);
                  }
                  async.until(test, iterator, callback);
              });
          }
          else {
              callback();
          }
      };
  
      async.doUntil = function (iterator, test, callback) {
          iterator(function (err) {
              if (err) {
                  return callback(err);
              }
              var args = Array.prototype.slice.call(arguments, 1);
              if (!test.apply(null, args)) {
                  async.doUntil(iterator, test, callback);
              }
              else {
                  callback();
              }
          });
      };
  
      async.queue = function (worker, concurrency) {
          if (concurrency === undefined) {
              concurrency = 1;
          }
          function _insert(q, data, pos, callback) {
            if (!q.started){
              q.started = true;
            }
            if (!_isArray(data)) {
                data = [data];
            }
            if(data.length == 0) {
               // call drain immediately if there are no tasks
               return async.setImmediate(function() {
                   if (q.drain) {
                       q.drain();
                   }
               });
            }
            _each(data, function(task) {
                var item = {
                    data: task,
                    callback: typeof callback === 'function' ? callback : null
                };
  
                if (pos) {
                  q.tasks.unshift(item);
                } else {
                  q.tasks.push(item);
                }
  
                if (q.saturated && q.tasks.length === q.concurrency) {
                    q.saturated();
                }
                async.setImmediate(q.process);
            });
          }
  
          var workers = 0;
          var q = {
              tasks: [],
              concurrency: concurrency,
              saturated: null,
              empty: null,
              drain: null,
              started: false,
              paused: false,
              push: function (data, callback) {
                _insert(q, data, false, callback);
              },
              kill: function () {
                q.drain = null;
                q.tasks = [];
              },
              unshift: function (data, callback) {
                _insert(q, data, true, callback);
              },
              process: function () {
                  if (!q.paused && workers < q.concurrency && q.tasks.length) {
                      var task = q.tasks.shift();
                      if (q.empty && q.tasks.length === 0) {
                          q.empty();
                      }
                      workers += 1;
                      var next = function () {
                          workers -= 1;
                          if (task.callback) {
                              task.callback.apply(task, arguments);
                          }
                          if (q.drain && q.tasks.length + workers === 0) {
                              q.drain();
                          }
                          q.process();
                      };
                      var cb = only_once(next);
                      worker(task.data, cb);
                  }
              },
              length: function () {
                  return q.tasks.length;
              },
              running: function () {
                  return workers;
              },
              idle: function() {
                  return q.tasks.length + workers === 0;
              },
              pause: function () {
                  if (q.paused === true) { return; }
                  q.paused = true;
                  q.process();
              },
              resume: function () {
                  if (q.paused === false) { return; }
                  q.paused = false;
                  q.process();
              }
          };
          return q;
      };
      
      async.priorityQueue = function (worker, concurrency) {
          
          function _compareTasks(a, b){
            return a.priority - b.priority;
          };
          
          function _binarySearch(sequence, item, compare) {
            var beg = -1,
                end = sequence.length - 1;
            while (beg < end) {
              var mid = beg + ((end - beg + 1) >>> 1);
              if (compare(item, sequence[mid]) >= 0) {
                beg = mid;
              } else {
                end = mid - 1;
              }
            }
            return beg;
          }
          
          function _insert(q, data, priority, callback) {
            if (!q.started){
              q.started = true;
            }
            if (!_isArray(data)) {
                data = [data];
            }
            if(data.length == 0) {
               // call drain immediately if there are no tasks
               return async.setImmediate(function() {
                   if (q.drain) {
                       q.drain();
                   }
               });
            }
            _each(data, function(task) {
                var item = {
                    data: task,
                    priority: priority,
                    callback: typeof callback === 'function' ? callback : null
                };
                
                q.tasks.splice(_binarySearch(q.tasks, item, _compareTasks) + 1, 0, item);
  
                if (q.saturated && q.tasks.length === q.concurrency) {
                    q.saturated();
                }
                async.setImmediate(q.process);
            });
          }
          
          // Start with a normal queue
          var q = async.queue(worker, concurrency);
          
          // Override push to accept second parameter representing priority
          q.push = function (data, priority, callback) {
            _insert(q, data, priority, callback);
          };
          
          // Remove unshift function
          delete q.unshift;
  
          return q;
      };
  
      async.cargo = function (worker, payload) {
          var working     = false,
              tasks       = [];
  
          var cargo = {
              tasks: tasks,
              payload: payload,
              saturated: null,
              empty: null,
              drain: null,
              drained: true,
              push: function (data, callback) {
                  if (!_isArray(data)) {
                      data = [data];
                  }
                  _each(data, function(task) {
                      tasks.push({
                          data: task,
                          callback: typeof callback === 'function' ? callback : null
                      });
                      cargo.drained = false;
                      if (cargo.saturated && tasks.length === payload) {
                          cargo.saturated();
                      }
                  });
                  async.setImmediate(cargo.process);
              },
              process: function process() {
                  if (working) return;
                  if (tasks.length === 0) {
                      if(cargo.drain && !cargo.drained) cargo.drain();
                      cargo.drained = true;
                      return;
                  }
  
                  var ts = typeof payload === 'number'
                              ? tasks.splice(0, payload)
                              : tasks.splice(0, tasks.length);
  
                  var ds = _map(ts, function (task) {
                      return task.data;
                  });
  
                  if(cargo.empty) cargo.empty();
                  working = true;
                  worker(ds, function () {
                      working = false;
  
                      var args = arguments;
                      _each(ts, function (data) {
                          if (data.callback) {
                              data.callback.apply(null, args);
                          }
                      });
  
                      process();
                  });
              },
              length: function () {
                  return tasks.length;
              },
              running: function () {
                  return working;
              }
          };
          return cargo;
      };
  
      var _console_fn = function (name) {
          return function (fn) {
              var args = Array.prototype.slice.call(arguments, 1);
              fn.apply(null, args.concat([function (err) {
                  var args = Array.prototype.slice.call(arguments, 1);
                  if (typeof console !== 'undefined') {
                      if (err) {
                          if (console.error) {
                              console.error(err);
                          }
                      }
                      else if (console[name]) {
                          _each(args, function (x) {
                              console[name](x);
                          });
                      }
                  }
              }]));
          };
      };
      async.log = _console_fn('log');
      async.dir = _console_fn('dir');
      /*async.info = _console_fn('info');
      async.warn = _console_fn('warn');
      async.error = _console_fn('error');*/
  
      async.memoize = function (fn, hasher) {
          var memo = {};
          var queues = {};
          hasher = hasher || function (x) {
              return x;
          };
          var memoized = function () {
              var args = Array.prototype.slice.call(arguments);
              var callback = args.pop();
              var key = hasher.apply(null, args);
              if (key in memo) {
                  async.nextTick(function () {
                      callback.apply(null, memo[key]);
                  });
              }
              else if (key in queues) {
                  queues[key].push(callback);
              }
              else {
                  queues[key] = [callback];
                  fn.apply(null, args.concat([function () {
                      memo[key] = arguments;
                      var q = queues[key];
                      delete queues[key];
                      for (var i = 0, l = q.length; i < l; i++) {
                        q[i].apply(null, arguments);
                      }
                  }]));
              }
          };
          memoized.memo = memo;
          memoized.unmemoized = fn;
          return memoized;
      };
  
      async.unmemoize = function (fn) {
        return function () {
          return (fn.unmemoized || fn).apply(null, arguments);
        };
      };
  
      async.times = function (count, iterator, callback) {
          var counter = [];
          for (var i = 0; i < count; i++) {
              counter.push(i);
          }
          return async.map(counter, iterator, callback);
      };
  
      async.timesSeries = function (count, iterator, callback) {
          var counter = [];
          for (var i = 0; i < count; i++) {
              counter.push(i);
          }
          return async.mapSeries(counter, iterator, callback);
      };
  
      async.seq = function (/* functions... */) {
          var fns = arguments;
          return function () {
              var that = this;
              var args = Array.prototype.slice.call(arguments);
              var callback = args.pop();
              async.reduce(fns, args, function (newargs, fn, cb) {
                  fn.apply(that, newargs.concat([function () {
                      var err = arguments[0];
                      var nextargs = Array.prototype.slice.call(arguments, 1);
                      cb(err, nextargs);
                  }]))
              },
              function (err, results) {
                  callback.apply(that, [err].concat(results));
              });
          };
      };
  
      async.compose = function (/* functions... */) {
        return async.seq.apply(null, Array.prototype.reverse.call(arguments));
      };
  
      var _applyEach = function (eachfn, fns /*args...*/) {
          var go = function () {
              var that = this;
              var args = Array.prototype.slice.call(arguments);
              var callback = args.pop();
              return eachfn(fns, function (fn, cb) {
                  fn.apply(that, args.concat([cb]));
              },
              callback);
          };
          if (arguments.length > 2) {
              var args = Array.prototype.slice.call(arguments, 2);
              return go.apply(this, args);
          }
          else {
              return go;
          }
      };
      async.applyEach = doParallel(_applyEach);
      async.applyEachSeries = doSeries(_applyEach);
  
      async.forever = function (fn, callback) {
          function next(err) {
              if (err) {
                  if (callback) {
                      return callback(err);
                  }
                  throw err;
              }
              fn(next);
          }
          next();
      };
  
      // Node.js
      if (typeof module !== 'undefined' && module.exports) {
          module.exports = async;
      }
      // AMD / RequireJS
      else if (typeof define !== 'undefined' && define.amd) {
          define([], function () {
              return async;
          });
      }
      // included directly via <script> tag
      else {
          root.async = async;
      }
  
  }());
  
  }).call(this,_dereq_("FWaASH"))
  },{"FWaASH":14}],12:[function(_dereq_,module,exports){
  if (typeof Object.create === 'function') {
    // implementation from standard node.js 'util' module
    module.exports = function inherits(ctor, superCtor) {
      ctor.super_ = superCtor
      ctor.prototype = Object.create(superCtor.prototype, {
        constructor: {
          value: ctor,
          enumerable: false,
          writable: true,
          configurable: true
        }
      });
    };
  } else {
    // old school shim for old browsers
    module.exports = function inherits(ctor, superCtor) {
      ctor.super_ = superCtor
      var TempCtor = function () {}
      TempCtor.prototype = superCtor.prototype
      ctor.prototype = new TempCtor()
      ctor.prototype.constructor = ctor
    }
  }
  
  },{}],13:[function(_dereq_,module,exports){
  (function (process){
  // Copyright Joyent, Inc. and other Node contributors.
  //
  // Permission is hereby granted, free of charge, to any person obtaining a
  // copy of this software and associated documentation files (the
  // "Software"), to deal in the Software without restriction, including
  // without limitation the rights to use, copy, modify, merge, publish,
  // distribute, sublicense, and/or sell copies of the Software, and to permit
  // persons to whom the Software is furnished to do so, subject to the
  // following conditions:
  //
  // The above copyright notice and this permission notice shall be included
  // in all copies or substantial portions of the Software.
  //
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  // USE OR OTHER DEALINGS IN THE SOFTWARE.
  
  // resolves . and .. elements in a path array with directory names there
  // must be no slashes, empty elements, or device names (c:\) in the array
  // (so also no leading and trailing slashes - it does not distinguish
  // relative and absolute paths)
  function normalizeArray(parts, allowAboveRoot) {
    // if the path tries to go above the root, `up` ends up > 0
    var up = 0;
    for (var i = parts.length - 1; i >= 0; i--) {
      var last = parts[i];
      if (last === '.') {
        parts.splice(i, 1);
      } else if (last === '..') {
        parts.splice(i, 1);
        up++;
      } else if (up) {
        parts.splice(i, 1);
        up--;
      }
    }
  
    // if the path is allowed to go above the root, restore leading ..s
    if (allowAboveRoot) {
      for (; up--; up) {
        parts.unshift('..');
      }
    }
  
    return parts;
  }
  
  // Split a filename into [root, dir, basename, ext], unix version
  // 'root' is just a slash, or nothing.
  var splitPathRe =
      /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;
  var splitPath = function(filename) {
    return splitPathRe.exec(filename).slice(1);
  };
  
  // path.resolve([from ...], to)
  // posix version
  exports.resolve = function() {
    var resolvedPath = '',
        resolvedAbsolute = false;
  
    for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
      var path = (i >= 0) ? arguments[i] : process.cwd();
  
      // Skip empty and invalid entries
      if (typeof path !== 'string') {
        throw new TypeError('Arguments to path.resolve must be strings');
      } else if (!path) {
        continue;
      }
  
      resolvedPath = path + '/' + resolvedPath;
      resolvedAbsolute = path.charAt(0) === '/';
    }
  
    // At this point the path should be resolved to a full absolute path, but
    // handle relative paths to be safe (might happen when process.cwd() fails)
  
    // Normalize the path
    resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {
      return !!p;
    }), !resolvedAbsolute).join('/');
  
    return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
  };
  
  // path.normalize(path)
  // posix version
  exports.normalize = function(path) {
    var isAbsolute = exports.isAbsolute(path),
        trailingSlash = substr(path, -1) === '/';
  
    // Normalize the path
    path = normalizeArray(filter(path.split('/'), function(p) {
      return !!p;
    }), !isAbsolute).join('/');
  
    if (!path && !isAbsolute) {
      path = '.';
    }
    if (path && trailingSlash) {
      path += '/';
    }
  
    return (isAbsolute ? '/' : '') + path;
  };
  
  // posix version
  exports.isAbsolute = function(path) {
    return path.charAt(0) === '/';
  };
  
  // posix version
  exports.join = function() {
    var paths = Array.prototype.slice.call(arguments, 0);
    return exports.normalize(filter(paths, function(p, index) {
      if (typeof p !== 'string') {
        throw new TypeError('Arguments to path.join must be strings');
      }
      return p;
    }).join('/'));
  };
  
  
  // path.relative(from, to)
  // posix version
  exports.relative = function(from, to) {
    from = exports.resolve(from).substr(1);
    to = exports.resolve(to).substr(1);
  
    function trim(arr) {
      var start = 0;
      for (; start < arr.length; start++) {
        if (arr[start] !== '') break;
      }
  
      var end = arr.length - 1;
      for (; end >= 0; end--) {
        if (arr[end] !== '') break;
      }
  
      if (start > end) return [];
      return arr.slice(start, end - start + 1);
    }
  
    var fromParts = trim(from.split('/'));
    var toParts = trim(to.split('/'));
  
    var length = Math.min(fromParts.length, toParts.length);
    var samePartsLength = length;
    for (var i = 0; i < length; i++) {
      if (fromParts[i] !== toParts[i]) {
        samePartsLength = i;
        break;
      }
    }
  
    var outputParts = [];
    for (var i = samePartsLength; i < fromParts.length; i++) {
      outputParts.push('..');
    }
  
    outputParts = outputParts.concat(toParts.slice(samePartsLength));
  
    return outputParts.join('/');
  };
  
  exports.sep = '/';
  exports.delimiter = ':';
  
  exports.dirname = function(path) {
    var result = splitPath(path),
        root = result[0],
        dir = result[1];
  
    if (!root && !dir) {
      // No dirname whatsoever
      return '.';
    }
  
    if (dir) {
      // It has a dirname, strip trailing slash
      dir = dir.substr(0, dir.length - 1);
    }
  
    return root + dir;
  };
  
  
  exports.basename = function(path, ext) {
    var f = splitPath(path)[2];
    // TODO: make this comparison case-insensitive on windows?
    if (ext && f.substr(-1 * ext.length) === ext) {
      f = f.substr(0, f.length - ext.length);
    }
    return f;
  };
  
  
  exports.extname = function(path) {
    return splitPath(path)[3];
  };
  
  function filter (xs, f) {
      if (xs.filter) return xs.filter(f);
      var res = [];
      for (var i = 0; i < xs.length; i++) {
          if (f(xs[i], i, xs)) res.push(xs[i]);
      }
      return res;
  }
  
  // String.prototype.substr - negative index don't work in IE8
  var substr = 'ab'.substr(-1) === 'b'
      ? function (str, start, len) { return str.substr(start, len) }
      : function (str, start, len) {
          if (start < 0) start = str.length + start;
          return str.substr(start, len);
      }
  ;
  
  }).call(this,_dereq_("FWaASH"))
  },{"FWaASH":14}],14:[function(_dereq_,module,exports){
  // shim for using process in browser
  
  var process = module.exports = {};
  
  process.nextTick = (function () {
      var canSetImmediate = typeof window !== 'undefined'
      && window.setImmediate;
      var canPost = typeof window !== 'undefined'
      && window.postMessage && window.addEventListener
      ;
  
      if (canSetImmediate) {
          return function (f) { return window.setImmediate(f) };
      }
  
      if (canPost) {
          var queue = [];
          window.addEventListener('message', function (ev) {
              var source = ev.source;
              if ((source === window || source === null) && ev.data === 'process-tick') {
                  ev.stopPropagation();
                  if (queue.length > 0) {
                      var fn = queue.shift();
                      fn();
                  }
              }
          }, true);
  
          return function nextTick(fn) {
              queue.push(fn);
              window.postMessage('process-tick', '*');
          };
      }
  
      return function nextTick(fn) {
          setTimeout(fn, 0);
      };
  })();
  
  process.title = 'browser';
  process.browser = true;
  process.env = {};
  process.argv = [];
  
  function noop() {}
  
  process.on = noop;
  process.addListener = noop;
  process.once = noop;
  process.off = noop;
  process.removeListener = noop;
  process.removeAllListeners = noop;
  process.emit = noop;
  
  process.binding = function (name) {
      throw new Error('process.binding is not supported');
  }
  
  // TODO(shtylman)
  process.cwd = function () { return '/' };
  process.chdir = function (dir) {
      throw new Error('process.chdir is not supported');
  };
  
  },{}],15:[function(_dereq_,module,exports){
  module.exports = function isBuffer(arg) {
    return arg && typeof arg === 'object'
      && typeof arg.copy === 'function'
      && typeof arg.fill === 'function'
      && typeof arg.readUInt8 === 'function';
  }
  },{}],16:[function(_dereq_,module,exports){
  (function (process,global){
  // Copyright Joyent, Inc. and other Node contributors.
  //
  // Permission is hereby granted, free of charge, to any person obtaining a
  // copy of this software and associated documentation files (the
  // "Software"), to deal in the Software without restriction, including
  // without limitation the rights to use, copy, modify, merge, publish,
  // distribute, sublicense, and/or sell copies of the Software, and to permit
  // persons to whom the Software is furnished to do so, subject to the
  // following conditions:
  //
  // The above copyright notice and this permission notice shall be included
  // in all copies or substantial portions of the Software.
  //
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
  // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
  // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  // USE OR OTHER DEALINGS IN THE SOFTWARE.
  
  var formatRegExp = /%[sdj%]/g;
  exports.format = function(f) {
    if (!isString(f)) {
      var objects = [];
      for (var i = 0; i < arguments.length; i++) {
        objects.push(inspect(arguments[i]));
      }
      return objects.join(' ');
    }
  
    var i = 1;
    var args = arguments;
    var len = args.length;
    var str = String(f).replace(formatRegExp, function(x) {
      if (x === '%%') return '%';
      if (i >= len) return x;
      switch (x) {
        case '%s': return String(args[i++]);
        case '%d': return Number(args[i++]);
        case '%j':
          try {
            return JSON.stringify(args[i++]);
          } catch (_) {
            return '[Circular]';
          }
        default:
          return x;
      }
    });
    for (var x = args[i]; i < len; x = args[++i]) {
      if (isNull(x) || !isObject(x)) {
        str += ' ' + x;
      } else {
        str += ' ' + inspect(x);
      }
    }
    return str;
  };
  
  
  // Mark that a method should not be used.
  // Returns a modified function which warns once by default.
  // If --no-deprecation is set, then it is a no-op.
  exports.deprecate = function(fn, msg) {
    // Allow for deprecating things in the process of starting up.
    if (isUndefined(global.process)) {
      return function() {
        return exports.deprecate(fn, msg).apply(this, arguments);
      };
    }
  
    if (process.noDeprecation === true) {
      return fn;
    }
  
    var warned = false;
    function deprecated() {
      if (!warned) {
        if (process.throwDeprecation) {
          throw new Error(msg);
        } else if (process.traceDeprecation) {
          console.trace(msg);
        } else {
          console.error(msg);
        }
        warned = true;
      }
      return fn.apply(this, arguments);
    }
  
    return deprecated;
  };
  
  
  var debugs = {};
  var debugEnviron;
  exports.debuglog = function(set) {
    if (isUndefined(debugEnviron))
      debugEnviron = process.env.NODE_DEBUG || '';
    set = set.toUpperCase();
    if (!debugs[set]) {
      if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) {
        var pid = process.pid;
        debugs[set] = function() {
          var msg = exports.format.apply(exports, arguments);
          console.error('%s %d: %s', set, pid, msg);
        };
      } else {
        debugs[set] = function() {};
      }
    }
    return debugs[set];
  };
  
  
  /**
   * Echos the value of a value. Trys to print the value out
   * in the best way possible given the different types.
   *
   * @param {Object} obj The object to print out.
   * @param {Object} opts Optional options object that alters the output.
   */
  /* legacy: obj, showHidden, depth, colors*/
  function inspect(obj, opts) {
    // default options
    var ctx = {
      seen: [],
      stylize: stylizeNoColor
    };
    // legacy...
    if (arguments.length >= 3) ctx.depth = arguments[2];
    if (arguments.length >= 4) ctx.colors = arguments[3];
    if (isBoolean(opts)) {
      // legacy...
      ctx.showHidden = opts;
    } else if (opts) {
      // got an "options" object
      exports._extend(ctx, opts);
    }
    // set default options
    if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
    if (isUndefined(ctx.depth)) ctx.depth = 2;
    if (isUndefined(ctx.colors)) ctx.colors = false;
    if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
    if (ctx.colors) ctx.stylize = stylizeWithColor;
    return formatValue(ctx, obj, ctx.depth);
  }
  exports.inspect = inspect;
  
  
  // http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
  inspect.colors = {
    'bold' : [1, 22],
    'italic' : [3, 23],
    'underline' : [4, 24],
    'inverse' : [7, 27],
    'white' : [37, 39],
    'grey' : [90, 39],
    'black' : [30, 39],
    'blue' : [34, 39],
    'cyan' : [36, 39],
    'green' : [32, 39],
    'magenta' : [35, 39],
    'red' : [31, 39],
    'yellow' : [33, 39]
  };
  
  // Don't use 'blue' not visible on cmd.exe
  inspect.styles = {
    'special': 'cyan',
    'number': 'yellow',
    'boolean': 'yellow',
    'undefined': 'grey',
    'null': 'bold',
    'string': 'green',
    'date': 'magenta',
    // "name": intentionally not styling
    'regexp': 'red'
  };
  
  
  function stylizeWithColor(str, styleType) {
    var style = inspect.styles[styleType];
  
    if (style) {
      return '\u001b[' + inspect.colors[style][0] + 'm' + str +
             '\u001b[' + inspect.colors[style][1] + 'm';
    } else {
      return str;
    }
  }
  
  
  function stylizeNoColor(str, styleType) {
    return str;
  }
  
  
  function arrayToHash(array) {
    var hash = {};
  
    array.forEach(function(val, idx) {
      hash[val] = true;
    });
  
    return hash;
  }
  
  
  function formatValue(ctx, value, recurseTimes) {
    // Provide a hook for user-specified inspect functions.
    // Check that value is an object with an inspect function on it
    if (ctx.customInspect &&
        value &&
        isFunction(value.inspect) &&
        // Filter out the util module, it's inspect function is special
        value.inspect !== exports.inspect &&
        // Also filter out any prototype objects using the circular check.
        !(value.constructor && value.constructor.prototype === value)) {
      var ret = value.inspect(recurseTimes, ctx);
      if (!isString(ret)) {
        ret = formatValue(ctx, ret, recurseTimes);
      }
      return ret;
    }
  
    // Primitive types cannot have properties
    var primitive = formatPrimitive(ctx, value);
    if (primitive) {
      return primitive;
    }
  
    // Look up the keys of the object.
    var keys = Object.keys(value);
    var visibleKeys = arrayToHash(keys);
  
    if (ctx.showHidden) {
      keys = Object.getOwnPropertyNames(value);
    }
  
    // IE doesn't make error fields non-enumerable
    // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx
    if (isError(value)
        && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) {
      return formatError(value);
    }
  
    // Some type of object without properties can be shortcutted.
    if (keys.length === 0) {
      if (isFunction(value)) {
        var name = value.name ? ': ' + value.name : '';
        return ctx.stylize('[Function' + name + ']', 'special');
      }
      if (isRegExp(value)) {
        return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
      }
      if (isDate(value)) {
        return ctx.stylize(Date.prototype.toString.call(value), 'date');
      }
      if (isError(value)) {
        return formatError(value);
      }
    }
  
    var base = '', array = false, braces = ['{', '}'];
  
    // Make Array say that they are Array
    if (isArray(value)) {
      array = true;
      braces = ['[', ']'];
    }
  
    // Make functions say that they are functions
    if (isFunction(value)) {
      var n = value.name ? ': ' + value.name : '';
      base = ' [Function' + n + ']';
    }
  
    // Make RegExps say that they are RegExps
    if (isRegExp(value)) {
      base = ' ' + RegExp.prototype.toString.call(value);
    }
  
    // Make dates with properties first say the date
    if (isDate(value)) {
      base = ' ' + Date.prototype.toUTCString.call(value);
    }
  
    // Make error with message first say the error
    if (isError(value)) {
      base = ' ' + formatError(value);
    }
  
    if (keys.length === 0 && (!array || value.length == 0)) {
      return braces[0] + base + braces[1];
    }
  
    if (recurseTimes < 0) {
      if (isRegExp(value)) {
        return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
      } else {
        return ctx.stylize('[Object]', 'special');
      }
    }
  
    ctx.seen.push(value);
  
    var output;
    if (array) {
      output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
    } else {
      output = keys.map(function(key) {
        return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
      });
    }
  
    ctx.seen.pop();
  
    return reduceToSingleString(output, base, braces);
  }
  
  
  function formatPrimitive(ctx, value) {
    if (isUndefined(value))
      return ctx.stylize('undefined', 'undefined');
    if (isString(value)) {
      var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
                                               .replace(/'/g, "\\'")
                                               .replace(/\\"/g, '"') + '\'';
      return ctx.stylize(simple, 'string');
    }
    if (isNumber(value))
      return ctx.stylize('' + value, 'number');
    if (isBoolean(value))
      return ctx.stylize('' + value, 'boolean');
    // For some reason typeof null is "object", so special case here.
    if (isNull(value))
      return ctx.stylize('null', 'null');
  }
  
  
  function formatError(value) {
    return '[' + Error.prototype.toString.call(value) + ']';
  }
  
  
  function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
    var output = [];
    for (var i = 0, l = value.length; i < l; ++i) {
      if (hasOwnProperty(value, String(i))) {
        output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
            String(i), true));
      } else {
        output.push('');
      }
    }
    keys.forEach(function(key) {
      if (!key.match(/^\d+$/)) {
        output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
            key, true));
      }
    });
    return output;
  }
  
  
  function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
    var name, str, desc;
    desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };
    if (desc.get) {
      if (desc.set) {
        str = ctx.stylize('[Getter/Setter]', 'special');
      } else {
        str = ctx.stylize('[Getter]', 'special');
      }
    } else {
      if (desc.set) {
        str = ctx.stylize('[Setter]', 'special');
      }
    }
    if (!hasOwnProperty(visibleKeys, key)) {
      name = '[' + key + ']';
    }
    if (!str) {
      if (ctx.seen.indexOf(desc.value) < 0) {
        if (isNull(recurseTimes)) {
          str = formatValue(ctx, desc.value, null);
        } else {
          str = formatValue(ctx, desc.value, recurseTimes - 1);
        }
        if (str.indexOf('\n') > -1) {
          if (array) {
            str = str.split('\n').map(function(line) {
              return '  ' + line;
            }).join('\n').substr(2);
          } else {
            str = '\n' + str.split('\n').map(function(line) {
              return '   ' + line;
            }).join('\n');
          }
        }
      } else {
        str = ctx.stylize('[Circular]', 'special');
      }
    }
    if (isUndefined(name)) {
      if (array && key.match(/^\d+$/)) {
        return str;
      }
      name = JSON.stringify('' + key);
      if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
        name = name.substr(1, name.length - 2);
        name = ctx.stylize(name, 'name');
      } else {
        name = name.replace(/'/g, "\\'")
                   .replace(/\\"/g, '"')
                   .replace(/(^"|"$)/g, "'");
        name = ctx.stylize(name, 'string');
      }
    }
  
    return name + ': ' + str;
  }
  
  
  function reduceToSingleString(output, base, braces) {
    var numLinesEst = 0;
    var length = output.reduce(function(prev, cur) {
      numLinesEst++;
      if (cur.indexOf('\n') >= 0) numLinesEst++;
      return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
    }, 0);
  
    if (length > 60) {
      return braces[0] +
             (base === '' ? '' : base + '\n ') +
             ' ' +
             output.join(',\n  ') +
             ' ' +
             braces[1];
    }
  
    return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
  }
  
  
  // NOTE: These type checking functions intentionally don't use `instanceof`
  // because it is fragile and can be easily faked with `Object.create()`.
  function isArray(ar) {
    return Array.isArray(ar);
  }
  exports.isArray = isArray;
  
  function isBoolean(arg) {
    return typeof arg === 'boolean';
  }
  exports.isBoolean = isBoolean;
  
  function isNull(arg) {
    return arg === null;
  }
  exports.isNull = isNull;
  
  function isNullOrUndefined(arg) {
    return arg == null;
  }
  exports.isNullOrUndefined = isNullOrUndefined;
  
  function isNumber(arg) {
    return typeof arg === 'number';
  }
  exports.isNumber = isNumber;
  
  function isString(arg) {
    return typeof arg === 'string';
  }
  exports.isString = isString;
  
  function isSymbol(arg) {
    return typeof arg === 'symbol';
  }
  exports.isSymbol = isSymbol;
  
  function isUndefined(arg) {
    return arg === void 0;
  }
  exports.isUndefined = isUndefined;
  
  function isRegExp(re) {
    return isObject(re) && objectToString(re) === '[object RegExp]';
  }
  exports.isRegExp = isRegExp;
  
  function isObject(arg) {
    return typeof arg === 'object' && arg !== null;
  }
  exports.isObject = isObject;
  
  function isDate(d) {
    return isObject(d) && objectToString(d) === '[object Date]';
  }
  exports.isDate = isDate;
  
  function isError(e) {
    return isObject(e) &&
        (objectToString(e) === '[object Error]' || e instanceof Error);
  }
  exports.isError = isError;
  
  function isFunction(arg) {
    return typeof arg === 'function';
  }
  exports.isFunction = isFunction;
  
  function isPrimitive(arg) {
    return arg === null ||
           typeof arg === 'boolean' ||
           typeof arg === 'number' ||
           typeof arg === 'string' ||
           typeof arg === 'symbol' ||  // ES6 symbol
           typeof arg === 'undefined';
  }
  exports.isPrimitive = isPrimitive;
  
  exports.isBuffer = _dereq_('./support/isBuffer');
  
  function objectToString(o) {
    return Object.prototype.toString.call(o);
  }
  
  
  function pad(n) {
    return n < 10 ? '0' + n.toString(10) : n.toString(10);
  }
  
  
  var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
                'Oct', 'Nov', 'Dec'];
  
  // 26 Feb 16:19:34
  function timestamp() {
    var d = new Date();
    var time = [pad(d.getHours()),
                pad(d.getMinutes()),
                pad(d.getSeconds())].join(':');
    return [d.getDate(), months[d.getMonth()], time].join(' ');
  }
  
  
  // log is just a thin wrapper to console.log that prepends a timestamp
  exports.log = function() {
    console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
  };
  
  
  /**
   * Inherit the prototype methods from one constructor into another.
   *
   * The Function.prototype.inherits from lang.js rewritten as a standalone
   * function (not on Function.prototype). NOTE: If this file is to be loaded
   * during bootstrapping this function needs to be rewritten using some native
   * functions as prototype setup using normal JavaScript does not work as
   * expected during bootstrapping (see mirror.js in r114903).
   *
   * @param {function} ctor Constructor function which needs to inherit the
   *     prototype.
   * @param {function} superCtor Constructor function to inherit prototype from.
   */
  exports.inherits = _dereq_('inherits');
  
  exports._extend = function(origin, add) {
    // Don't do anything if add isn't an object
    if (!add || !isObject(add)) return origin;
  
    var keys = Object.keys(add);
    var i = keys.length;
    while (i--) {
      origin[keys[i]] = add[keys[i]];
    }
    return origin;
  };
  
  function hasOwnProperty(obj, prop) {
    return Object.prototype.hasOwnProperty.call(obj, prop);
  }
  
  }).call(this,_dereq_("FWaASH"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  },{"./support/isBuffer":15,"FWaASH":14,"inherits":12}],17:[function(_dereq_,module,exports){
  'use strict';
  
  var utils = _dereq_('./utils')
    , pathm = _dereq_('path')
    , fs = _dereq_('./fileSystem');
  
  var wrapSuccess = utils.wrapSuccess
    , wrapFail = utils.wrapFail;
  
  exports.getFsInstance = fs.getInstance;
  
  exports.appendFile = function(path, data, callback) {
    fs.writeFile(path, data, callback, true);
  };
  
  
  exports.writeFile = function(path, data, callback) {
    fs.writeFile(path, data, callback, false);
  };
  
  
  exports.readFile = function(path, opts, callback) {
    if (typeof opts === 'function') {
      callback = opts;
      opts = {
        encoding: 'utf8'
      };
    }
  
    var success = wrapSuccess(callback)
      , fail = wrapFail(callback);
  
    fs.getFile(path, function(err, fileEntry) {
      fileEntry.file(function(file) {
        var reader = new FileReader();
  
        reader.onloadend = function(evt) {
          success(evt.target.result);
        };
  
        reader.onerror = function(err) {
          fail(err);
        };
  
        if (opts.encoding === 'utf8') {
          reader.readAsText(file);
        } else {
          reader.readAsDataURL(file);
        }
      }, fail);
    });
  };
  
  
  exports.unlink = function(path, callback) {
    var success = wrapSuccess(callback)
      , fail = wrapFail(callback);
  
    fs.getFile(path, function(err, file) {
      if (err) {
        fail(err);
      } else {
        file.remove(success, fail);
      }
    });
  };
  
  
  exports.readdir = function(path, callback) {
    var success = wrapSuccess(callback)
      , fail = wrapFail(callback);
  
    fs.getDirectory(path, function(err, dirEntry) {
      if (err) {
        fail(err);
      } else {
        var directoryReader = dirEntry.createReader();
        directoryReader.readEntries(success, fail);
      }
    });
  };
  
  
  exports.mkdir = function(path, callback) {
    var newFolderName = pathm.basename(path)
      , basePath = pathm.dirname(path)
      , success = utils.wrapSuccess(callback)
      , fail = utils.wrapFail(callback)
      , opts = {
        create: true,
        exclusive: true
      };
  
    if (basePath === '.') {
      fs.getDirectory(newFolderName, opts, callback);
    } else {
      fs.getDirectory(basePath, function (err, dir) {
        if (err) {
          callback(err, null);
        } else {
          dir.getDirectory(newFolderName, opts, success, fail);
        }
      });
    }
  };
  
  
  /**
   * Remove a directory.
   * The FileSystem API expects directories to be empty but returns a
   * non-informative error on Android and possibly iOS so we check here
   * to ensure users know why directory deletes might fail.
   * @param  {String}   path
   * @param  {Function} callback
   */
  exports.rmdir = function(path, callback) {
    var success = wrapSuccess(callback)
      , fail = wrapFail(callback);
  
    this.readdir(path, function(err, list) {
      if (err) {
        fail(err);
      } else if (list && list.length > 0) {
        fail('ENOTEMPTY: Directory must be empty');
      } else {
        fs.getDirectory(path, function(err, dirEntry) {
          if (err) {
            fail(err);
          } else {
            dirEntry.remove(success, fail);
          }
        });
      }
    });
  };
  
  
  exports.exists = function(path, callback) {
    var success = wrapSuccess(callback)
      , fail = wrapFail(callback);
  
    fs.getFile(path, {
      // Don't create the file, just look for it
      create: false
    }, function(err) {
      if (err && err.code === 1) { // NOT FOUND
        // If the file isn't found we don't want an error, pass false!
        success(false);
      } else if (err) {
        // An actual error occured, pass it along
        fail(err);
      } else {
        success(true);
      }
    });
  };
  
  
  exports.stat = function(path, callback) {
    var success = wrapSuccess(callback)
      , fail = wrapFail(callback)
      , fn = fs.getFile;
  
    // TODO: Perhaps check for folder AND file instead, use whichever exists
    if (utils.isDirectory(path)) {
      fn = fs.getDirectory;
    }
  
    fn(path, function(err, res) {
      if (err) {
        fail(err);
      } else {
        res.getMetadata(success, fail);
      }
    });
  };
  
  
  /**
   * Initialise the file system component for use.
   * @param {Number}     [quota]
   * @param {Function}   callback
   */
  exports.init = function(bytes, callback) {
    fs.init(bytes, function(err) {
      if (err) {
        callback(err, null);
      } else {
        fs.getInstance(function(err /*, instance */) {
          callback(err, null);
        });
      }
    });
  };
  
  },{"./fileSystem":18,"./utils":19,"path":13}],18:[function(_dereq_,module,exports){
  'use strict';
  
  var utils = _dereq_('./utils')
    , pathm = _dereq_('path');
  
  var DEFAULT_QUOTA = (10 * 1024 * 1024); // 10MB
  
  var fileSystem = null;
  
  /**
   * Get a FileSystem instance.
   * @param {Function} callback
   */
  exports.getInstance = function(callback) {
    if (fileSystem) {
      callback(null, fileSystem);
    } else {
      init(null, callback);
    }
  };
  
  
  /**
   * Initialises access to browser File System
   * @param {Number}      bytes
   * @param {Function}    callback
   */
  var init = exports.init = function(bytes, callback) {
    requestQuota(bytes, function(err, grantedBytes) {
      if (err) {
        return callback(err, null);
      } else {
        requestFileSystem(grantedBytes, function(instance) {
          fileSystem = instance;
          callback(null, grantedBytes);
        }, function(err) {
          callback(err, null);
        });
      }
    });
  };
  
  
  /**
   * Write data to a file optionally appending it.
   * @param {String}      path
   * @param {Mixed}       data
   * @param {Function}    callback
   * @param {Boolean}     append
   */
  exports.writeFile = function(path, data, callback, append) {
    var fail = utils.wrapFail(callback)
      , success = utils.wrapSuccess(callback);
  
    this.getFile(path, {
      create: true,
      exclusive: false
    }, function(err, file) {
      if (err) {
        return callback(err, null);
      } else {
        file.createWriter(function(writer) {
          writer.onwrite = function(/*evt*/) {
            success(file.toURL());
          };
  
          writer.onerror = function(evt) {
            fail(evt.target.error);
          };
  
          if (append === true) {
            writer.seek(writer.length);
          }
  
          if (utils.isMobile()) {
            writer.write(data);
          } else {
            // Only desktop has blob support AFAIK
            writer.write(new Blob([data], {
              type: 'text/plain'
            }));
          }
        }, fail);
      }
    });
  };
  
  
  /**
   * Get a directory specified by path.
   * By default if the dir does not exist it is not created.
   * @param {String}      path
   * @param {Object}      [opts]
   * @param {Function}    callback
   */
  exports.getDirectory = function(path, opts, callback) {
    if (!callback) {
      callback = opts;
      opts = {
        create: false
      };
    }
  
    var success = utils.wrapSuccess(callback)
      , fail = utils.wrapFail(callback);
  
    fileSystem.root.getDirectory(path, opts, success, fail);
  };
  
  
  /**
   * Get a file at a specified path.
   * By default if the file does not exist it is not created.
   * @param {String}      path
   * @param {Object}      [opts]
   * @param {Function}    callback
   */
  exports.getFile = function(path, opts, callback) {
    if (!callback) {
      callback = opts;
      opts = {
        create: false
      };
    }
  
    var fileName = pathm.basename(path)
      , basePath = pathm.dirname(path)
      , success = utils.wrapSuccess(callback)
      , fail = utils.wrapFail(callback);
  
    function doGet (dirRef) {
      dirRef.getFile(fileName, opts, success, fail);
    }
  
    if (basePath === '.') {
      // File is in root directory
      doGet(fileSystem.root);
    } else {
      // Need to get container directory ref for the requested file
      this.getDirectory(basePath, function (err, dir) {
        if (err) {
          callback(err, null);
        } else {
          doGet(dir);
        }
      });
    }
  };
  
  
  /**
   * Request access to the file system.
   * This is called only after quota is granted.
   * @param {Number}       bytes
   * @param {Function}     success
   * @param {Function}     fail
   */
  function requestFileSystem(bytes, success, fail) {
    // These are in order of preference due to some being deprecated
    if (window.navigator.webkitRequestFileSystem) {
      window.navigator.webkitRequestFileSystem(bytes, success, fail);
    } else if (window.requestFileSystem) {
      window.requestFileSystem(
        window.LocalFileSystem.PERSISTENT,
        bytes,
        success,
        fail
      );
    } else if (window.webkitRequestFileSystem) {
      window.webkitRequestFileSystem(
        window.PERSISTENT_FLAG,
        bytes,
        success,
        fail
      );
    } else {
      fail('NO_SUPPORT');
    }
  }
  
  
  /**
   * Request a quota from the FileSystem.
   * @param {Number}     bytes
   * @param {Function}   callback
   */
  function requestQuota(quota, callback) {
    // Allow user overide the default quota
    quota = quota || DEFAULT_QUOTA;
  
    function success(bytes) {
      callback(null, bytes);
    }
  
    function fail(err) {
      callback(err, null);
    }
  
    // These are in order of preference due to some being deprecated
    if (navigator.webkitPersistentStorage &&
        navigator.webkitPersistentStorage.requestQuota) {
      navigator.webkitPersistentStorage.requestQuota(quota, success, fail);
    } else if (window.webkitStorageInfo &&
        window.webkitStorageInfo.requestQuota) {
      window.webkitStorageInfo.requestQuota(
        window.PERSISTENT,
        quota,
        success,
        fail
      );
    } else if (window.requestFileSystem) {
      // PhoneGap apps should request a 0 quota
      if (utils.isPhoneGap() === true) {
        quota = 0;
      }
  
      success(quota);
    } else {
      fail('NO_SUPPORT');
    }
  }
  
  },{"./utils":19,"path":13}],19:[function(_dereq_,module,exports){
  'use strict';
  
  /**
   * Detect is the device a mobile device.
   * @return {Boolean}
   */
  exports.isMobile = function() {
    var ua = window.navigator.userAgent;
    return (ua.match(/Android|iPad|iPhone|iPod|Windows Phone/) !== null);
  };
  
  
  /**
   * Determine if this is a PhoneGap application.
   * @return {Boolean}
   */
  exports.isPhoneGap = function() {
    // TODO: Improve this...
    var proto = window.location.protocol;
    return (this.isMobile() && proto.indexOf('file') !== -1);
  };
  
  
  /**
   * Determine if FileSystem is supported.
   * @return {Boolean}
   */
  exports.supportsFileSystem = function() {
    if (this.isPhoneGap() === true) {
      return true;
    }
  
    // TODO: Test this works, Opera (WebKit) and Chrome
    return window.navigator.userAgent.match(/Chrome|Opera/);
  };
  
  
  /**
   * Wrap a callback for use as a success callback.
   * @param    {Function} callback
   * @return   {Function}
   */
  exports.wrapSuccess = function(callback) {
    return function() {
      var args = [null].concat(Array.prototype.slice.call(arguments));
  
      callback.apply(callback, args);
    };
  };
  
  
  /**
   * Wrap a callback for use as a failure callback.
   * @param    {Function} callback
   * @return   {Function}
   */
  exports.wrapFail = function(callback) {
    return function() {
      var args = Array.prototype.slice.call(arguments)
        , e = args[0];
  
      callback.apply(callback, [e, null]);
    };
  };
  
  
  /**
   * Check is provided path a directory.
   * @param  {String} path
   * @return {Boolean}
   */
  exports.isDirectory = function(path) {
    return (path.lastIndexOf('/') === (path.length - 1));
  };
  
  },{}],20:[function(_dereq_,module,exports){
  (function (global){
  /**
   * @license
   * Lo-Dash 2.4.1 (Custom Build) <http://lodash.com/>
   * Build: `lodash modern -o ./dist/lodash.js`
   * Copyright 2012-2013 The Dojo Foundation <http://dojofoundation.org/>
   * Based on Underscore.js 1.5.2 <http://underscorejs.org/LICENSE>
   * Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
   * Available under MIT license <http://lodash.com/license>
   */
  ;(function() {
  
    /** Used as a safe reference for `undefined` in pre ES5 environments */
    var undefined;
  
    /** Used to pool arrays and objects used internally */
    var arrayPool = [],
        objectPool = [];
  
    /** Used to generate unique IDs */
    var idCounter = 0;
  
    /** Used to prefix keys to avoid issues with `__proto__` and properties on `Object.prototype` */
    var keyPrefix = +new Date + '';
  
    /** Used as the size when optimizations are enabled for large arrays */
    var largeArraySize = 75;
  
    /** Used as the max size of the `arrayPool` and `objectPool` */
    var maxPoolSize = 40;
  
    /** Used to detect and test whitespace */
    var whitespace = (
      // whitespace
      ' \t\x0B\f\xA0\ufeff' +
  
      // line terminators
      '\n\r\u2028\u2029' +
  
      // unicode category "Zs" space separators
      '\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000'
    );
  
    /** Used to match empty string literals in compiled template source */
    var reEmptyStringLeading = /\b__p \+= '';/g,
        reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
        reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
  
    /**
     * Used to match ES6 template delimiters
     * http://people.mozilla.org/~jorendorff/es6-draft.html#sec-literals-string-literals
     */
    var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
  
    /** Used to match regexp flags from their coerced string values */
    var reFlags = /\w*$/;
  
    /** Used to detected named functions */
    var reFuncName = /^\s*function[ \n\r\t]+\w/;
  
    /** Used to match "interpolate" template delimiters */
    var reInterpolate = /<%=([\s\S]+?)%>/g;
  
    /** Used to match leading whitespace and zeros to be removed */
    var reLeadingSpacesAndZeros = RegExp('^[' + whitespace + ']*0+(?=.$)');
  
    /** Used to ensure capturing order of template delimiters */
    var reNoMatch = /($^)/;
  
    /** Used to detect functions containing a `this` reference */
    var reThis = /\bthis\b/;
  
    /** Used to match unescaped characters in compiled string literals */
    var reUnescapedString = /['\n\r\t\u2028\u2029\\]/g;
  
    /** Used to assign default `context` object properties */
    var contextProps = [
      'Array', 'Boolean', 'Date', 'Function', 'Math', 'Number', 'Object',
      'RegExp', 'String', '_', 'attachEvent', 'clearTimeout', 'isFinite', 'isNaN',
      'parseInt', 'setTimeout'
    ];
  
    /** Used to make template sourceURLs easier to identify */
    var templateCounter = 0;
  
    /** `Object#toString` result shortcuts */
    var argsClass = '[object Arguments]',
        arrayClass = '[object Array]',
        boolClass = '[object Boolean]',
        dateClass = '[object Date]',
        funcClass = '[object Function]',
        numberClass = '[object Number]',
        objectClass = '[object Object]',
        regexpClass = '[object RegExp]',
        stringClass = '[object String]';
  
    /** Used to identify object classifications that `_.clone` supports */
    var cloneableClasses = {};
    cloneableClasses[funcClass] = false;
    cloneableClasses[argsClass] = cloneableClasses[arrayClass] =
    cloneableClasses[boolClass] = cloneableClasses[dateClass] =
    cloneableClasses[numberClass] = cloneableClasses[objectClass] =
    cloneableClasses[regexpClass] = cloneableClasses[stringClass] = true;
  
    /** Used as an internal `_.debounce` options object */
    var debounceOptions = {
      'leading': false,
      'maxWait': 0,
      'trailing': false
    };
  
    /** Used as the property descriptor for `__bindData__` */
    var descriptor = {
      'configurable': false,
      'enumerable': false,
      'value': null,
      'writable': false
    };
  
    /** Used to determine if values are of the language type Object */
    var objectTypes = {
      'boolean': false,
      'function': true,
      'object': true,
      'number': false,
      'string': false,
      'undefined': false
    };
  
    /** Used to escape characters for inclusion in compiled string literals */
    var stringEscapes = {
      '\\': '\\',
      "'": "'",
      '\n': 'n',
      '\r': 'r',
      '\t': 't',
      '\u2028': 'u2028',
      '\u2029': 'u2029'
    };
  
    /** Used as a reference to the global object */
    var root = (objectTypes[typeof window] && window) || this;
  
    /** Detect free variable `exports` */
    var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports;
  
    /** Detect free variable `module` */
    var freeModule = objectTypes[typeof module] && module && !module.nodeType && module;
  
    /** Detect the popular CommonJS extension `module.exports` */
    var moduleExports = freeModule && freeModule.exports === freeExports && freeExports;
  
    /** Detect free variable `global` from Node.js or Browserified code and use it as `root` */
    var freeGlobal = objectTypes[typeof global] && global;
    if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal)) {
      root = freeGlobal;
    }
  
    /*--------------------------------------------------------------------------*/
  
    /**
     * The base implementation of `_.indexOf` without support for binary searches
     * or `fromIndex` constraints.
     *
     * @private
     * @param {Array} array The array to search.
     * @param {*} value The value to search for.
     * @param {number} [fromIndex=0] The index to search from.
     * @returns {number} Returns the index of the matched value or `-1`.
     */
    function baseIndexOf(array, value, fromIndex) {
      var index = (fromIndex || 0) - 1,
          length = array ? array.length : 0;
  
      while (++index < length) {
        if (array[index] === value) {
          return index;
        }
      }
      return -1;
    }
  
    /**
     * An implementation of `_.contains` for cache objects that mimics the return
     * signature of `_.indexOf` by returning `0` if the value is found, else `-1`.
     *
     * @private
     * @param {Object} cache The cache object to inspect.
     * @param {*} value The value to search for.
     * @returns {number} Returns `0` if `value` is found, else `-1`.
     */
    function cacheIndexOf(cache, value) {
      var type = typeof value;
      cache = cache.cache;
  
      if (type == 'boolean' || value == null) {
        return cache[value] ? 0 : -1;
      }
      if (type != 'number' && type != 'string') {
        type = 'object';
      }
      var key = type == 'number' ? value : keyPrefix + value;
      cache = (cache = cache[type]) && cache[key];
  
      return type == 'object'
        ? (cache && baseIndexOf(cache, value) > -1 ? 0 : -1)
        : (cache ? 0 : -1);
    }
  
    /**
     * Adds a given value to the corresponding cache object.
     *
     * @private
     * @param {*} value The value to add to the cache.
     */
    function cachePush(value) {
      var cache = this.cache,
          type = typeof value;
  
      if (type == 'boolean' || value == null) {
        cache[value] = true;
      } else {
        if (type != 'number' && type != 'string') {
          type = 'object';
        }
        var key = type == 'number' ? value : keyPrefix + value,
            typeCache = cache[type] || (cache[type] = {});
  
        if (type == 'object') {
          (typeCache[key] || (typeCache[key] = [])).push(value);
        } else {
          typeCache[key] = true;
        }
      }
    }
  
    /**
     * Used by `_.max` and `_.min` as the default callback when a given
     * collection is a string value.
     *
     * @private
     * @param {string} value The character to inspect.
     * @returns {number} Returns the code unit of given character.
     */
    function charAtCallback(value) {
      return value.charCodeAt(0);
    }
  
    /**
     * Used by `sortBy` to compare transformed `collection` elements, stable sorting
     * them in ascending order.
     *
     * @private
     * @param {Object} a The object to compare to `b`.
     * @param {Object} b The object to compare to `a`.
     * @returns {number} Returns the sort order indicator of `1` or `-1`.
     */
    function compareAscending(a, b) {
      var ac = a.criteria,
          bc = b.criteria,
          index = -1,
          length = ac.length;
  
      while (++index < length) {
        var value = ac[index],
            other = bc[index];
  
        if (value !== other) {
          if (value > other || typeof value == 'undefined') {
            return 1;
          }
          if (value < other || typeof other == 'undefined') {
            return -1;
          }
        }
      }
      // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications
      // that causes it, under certain circumstances, to return the same value for
      // `a` and `b`. See https://github.com/jashkenas/underscore/pull/1247
      //
      // This also ensures a stable sort in V8 and other engines.
      // See http://code.google.com/p/v8/issues/detail?id=90
      return a.index - b.index;
    }
  
    /**
     * Creates a cache object to optimize linear searches of large arrays.
     *
     * @private
     * @param {Array} [array=[]] The array to search.
     * @returns {null|Object} Returns the cache object or `null` if caching should not be used.
     */
    function createCache(array) {
      var index = -1,
          length = array.length,
          first = array[0],
          mid = array[(length / 2) | 0],
          last = array[length - 1];
  
      if (first && typeof first == 'object' &&
          mid && typeof mid == 'object' && last && typeof last == 'object') {
        return false;
      }
      var cache = getObject();
      cache['false'] = cache['null'] = cache['true'] = cache['undefined'] = false;
  
      var result = getObject();
      result.array = array;
      result.cache = cache;
      result.push = cachePush;
  
      while (++index < length) {
        result.push(array[index]);
      }
      return result;
    }
  
    /**
     * Used by `template` to escape characters for inclusion in compiled
     * string literals.
     *
     * @private
     * @param {string} match The matched character to escape.
     * @returns {string} Returns the escaped character.
     */
    function escapeStringChar(match) {
      return '\\' + stringEscapes[match];
    }
  
    /**
     * Gets an array from the array pool or creates a new one if the pool is empty.
     *
     * @private
     * @returns {Array} The array from the pool.
     */
    function getArray() {
      return arrayPool.pop() || [];
    }
  
    /**
     * Gets an object from the object pool or creates a new one if the pool is empty.
     *
     * @private
     * @returns {Object} The object from the pool.
     */
    function getObject() {
      return objectPool.pop() || {
        'array': null,
        'cache': null,
        'criteria': null,
        'false': false,
        'index': 0,
        'null': false,
        'number': null,
        'object': null,
        'push': null,
        'string': null,
        'true': false,
        'undefined': false,
        'value': null
      };
    }
  
    /**
     * Releases the given array back to the array pool.
     *
     * @private
     * @param {Array} [array] The array to release.
     */
    function releaseArray(array) {
      array.length = 0;
      if (arrayPool.length < maxPoolSize) {
        arrayPool.push(array);
      }
    }
  
    /**
     * Releases the given object back to the object pool.
     *
     * @private
     * @param {Object} [object] The object to release.
     */
    function releaseObject(object) {
      var cache = object.cache;
      if (cache) {
        releaseObject(cache);
      }
      object.array = object.cache = object.criteria = object.object = object.number = object.string = object.value = null;
      if (objectPool.length < maxPoolSize) {
        objectPool.push(object);
      }
    }
  
    /**
     * Slices the `collection` from the `start` index up to, but not including,
     * the `end` index.
     *
     * Note: This function is used instead of `Array#slice` to support node lists
     * in IE < 9 and to ensure dense arrays are returned.
     *
     * @private
     * @param {Array|Object|string} collection The collection to slice.
     * @param {number} start The start index.
     * @param {number} end The end index.
     * @returns {Array} Returns the new array.
     */
    function slice(array, start, end) {
      start || (start = 0);
      if (typeof end == 'undefined') {
        end = array ? array.length : 0;
      }
      var index = -1,
          length = end - start || 0,
          result = Array(length < 0 ? 0 : length);
  
      while (++index < length) {
        result[index] = array[start + index];
      }
      return result;
    }
  
    /*--------------------------------------------------------------------------*/
  
    /**
     * Create a new `lodash` function using the given context object.
     *
     * @static
     * @memberOf _
     * @category Utilities
     * @param {Object} [context=root] The context object.
     * @returns {Function} Returns the `lodash` function.
     */
    function runInContext(context) {
      // Avoid issues with some ES3 environments that attempt to use values, named
      // after built-in constructors like `Object`, for the creation of literals.
      // ES5 clears this up by stating that literals must use built-in constructors.
      // See http://es5.github.io/#x11.1.5.
      context = context ? _.defaults(root.Object(), context, _.pick(root, contextProps)) : root;
  
      /** Native constructor references */
      var Array = context.Array,
          Boolean = context.Boolean,
          Date = context.Date,
          Function = context.Function,
          Math = context.Math,
          Number = context.Number,
          Object = context.Object,
          RegExp = context.RegExp,
          String = context.String,
          TypeError = context.TypeError;
  
      /**
       * Used for `Array` method references.
       *
       * Normally `Array.prototype` would suffice, however, using an array literal
       * avoids issues in Narwhal.
       */
      var arrayRef = [];
  
      /** Used for native method references */
      var objectProto = Object.prototype;
  
      /** Used to restore the original `_` reference in `noConflict` */
      var oldDash = context._;
  
      /** Used to resolve the internal [[Class]] of values */
      var toString = objectProto.toString;
  
      /** Used to detect if a method is native */
      var reNative = RegExp('^' +
        String(toString)
          .replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
          .replace(/toString| for [^\]]+/g, '.*?') + '$'
      );
  
      /** Native method shortcuts */
      var ceil = Math.ceil,
          clearTimeout = context.clearTimeout,
          floor = Math.floor,
          fnToString = Function.prototype.toString,
          getPrototypeOf = isNative(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf,
          hasOwnProperty = objectProto.hasOwnProperty,
          push = arrayRef.push,
          setTimeout = context.setTimeout,
          splice = arrayRef.splice,
          unshift = arrayRef.unshift;
  
      /** Used to set meta data on functions */
      var defineProperty = (function() {
        // IE 8 only accepts DOM elements
        try {
          var o = {},
              func = isNative(func = Object.defineProperty) && func,
              result = func(o, o, o) && func;
        } catch(e) { }
        return result;
      }());
  
      /* Native method shortcuts for methods with the same name as other `lodash` methods */
      var nativeCreate = isNative(nativeCreate = Object.create) && nativeCreate,
          nativeIsArray = isNative(nativeIsArray = Array.isArray) && nativeIsArray,
          nativeIsFinite = context.isFinite,
          nativeIsNaN = context.isNaN,
          nativeKeys = isNative(nativeKeys = Object.keys) && nativeKeys,
          nativeMax = Math.max,
          nativeMin = Math.min,
          nativeParseInt = context.parseInt,
          nativeRandom = Math.random;
  
      /** Used to lookup a built-in constructor by [[Class]] */
      var ctorByClass = {};
      ctorByClass[arrayClass] = Array;
      ctorByClass[boolClass] = Boolean;
      ctorByClass[dateClass] = Date;
      ctorByClass[funcClass] = Function;
      ctorByClass[objectClass] = Object;
      ctorByClass[numberClass] = Number;
      ctorByClass[regexpClass] = RegExp;
      ctorByClass[stringClass] = String;
  
      /*--------------------------------------------------------------------------*/
  
      /**
       * Creates a `lodash` object which wraps the given value to enable intuitive
       * method chaining.
       *
       * In addition to Lo-Dash methods, wrappers also have the following `Array` methods:
       * `concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`, `splice`,
       * and `unshift`
       *
       * Chaining is supported in custom builds as long as the `value` method is
       * implicitly or explicitly included in the build.
       *
       * The chainable wrapper functions are:
       * `after`, `assign`, `bind`, `bindAll`, `bindKey`, `chain`, `compact`,
       * `compose`, `concat`, `countBy`, `create`, `createCallback`, `curry`,
       * `debounce`, `defaults`, `defer`, `delay`, `difference`, `filter`, `flatten`,
       * `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, `forOwnRight`,
       * `functions`, `groupBy`, `indexBy`, `initial`, `intersection`, `invert`,
       * `invoke`, `keys`, `map`, `max`, `memoize`, `merge`, `min`, `object`, `omit`,
       * `once`, `pairs`, `partial`, `partialRight`, `pick`, `pluck`, `pull`, `push`,
       * `range`, `reject`, `remove`, `rest`, `reverse`, `shuffle`, `slice`, `sort`,
       * `sortBy`, `splice`, `tap`, `throttle`, `times`, `toArray`, `transform`,
       * `union`, `uniq`, `unshift`, `unzip`, `values`, `where`, `without`, `wrap`,
       * and `zip`
       *
       * The non-chainable wrapper functions are:
       * `clone`, `cloneDeep`, `contains`, `escape`, `every`, `find`, `findIndex`,
       * `findKey`, `findLast`, `findLastIndex`, `findLastKey`, `has`, `identity`,
       * `indexOf`, `isArguments`, `isArray`, `isBoolean`, `isDate`, `isElement`,
       * `isEmpty`, `isEqual`, `isFinite`, `isFunction`, `isNaN`, `isNull`, `isNumber`,
       * `isObject`, `isPlainObject`, `isRegExp`, `isString`, `isUndefined`, `join`,
       * `lastIndexOf`, `mixin`, `noConflict`, `parseInt`, `pop`, `random`, `reduce`,
       * `reduceRight`, `result`, `shift`, `size`, `some`, `sortedIndex`, `runInContext`,
       * `template`, `unescape`, `uniqueId`, and `value`
       *
       * The wrapper functions `first` and `last` return wrapped values when `n` is
       * provided, otherwise they return unwrapped values.
       *
       * Explicit chaining can be enabled by using the `_.chain` method.
       *
       * @name _
       * @constructor
       * @category Chaining
       * @param {*} value The value to wrap in a `lodash` instance.
       * @returns {Object} Returns a `lodash` instance.
       * @example
       *
       * var wrapped = _([1, 2, 3]);
       *
       * // returns an unwrapped value
       * wrapped.reduce(function(sum, num) {
       *   return sum + num;
       * });
       * // => 6
       *
       * // returns a wrapped value
       * var squares = wrapped.map(function(num) {
       *   return num * num;
       * });
       *
       * _.isArray(squares);
       * // => false
       *
       * _.isArray(squares.value());
       * // => true
       */
      function lodash(value) {
        // don't wrap if already wrapped, even if wrapped by a different `lodash` constructor
        return (value && typeof value == 'object' && !isArray(value) && hasOwnProperty.call(value, '__wrapped__'))
         ? value
         : new lodashWrapper(value);
      }
  
      /**
       * A fast path for creating `lodash` wrapper objects.
       *
       * @private
       * @param {*} value The value to wrap in a `lodash` instance.
       * @param {boolean} chainAll A flag to enable chaining for all methods
       * @returns {Object} Returns a `lodash` instance.
       */
      function lodashWrapper(value, chainAll) {
        this.__chain__ = !!chainAll;
        this.__wrapped__ = value;
      }
      // ensure `new lodashWrapper` is an instance of `lodash`
      lodashWrapper.prototype = lodash.prototype;
  
      /**
       * An object used to flag environments features.
       *
       * @static
       * @memberOf _
       * @type Object
       */
      var support = lodash.support = {};
  
      /**
       * Detect if functions can be decompiled by `Function#toString`
       * (all but PS3 and older Opera mobile browsers & avoided in Windows 8 apps).
       *
       * @memberOf _.support
       * @type boolean
       */
      support.funcDecomp = !isNative(context.WinRTError) && reThis.test(runInContext);
  
      /**
       * Detect if `Function#name` is supported (all but IE).
       *
       * @memberOf _.support
       * @type boolean
       */
      support.funcNames = typeof Function.name == 'string';
  
      /**
       * By default, the template delimiters used by Lo-Dash are similar to those in
       * embedded Ruby (ERB). Change the following template settings to use alternative
       * delimiters.
       *
       * @static
       * @memberOf _
       * @type Object
       */
      lodash.templateSettings = {
  
        /**
         * Used to detect `data` property values to be HTML-escaped.
         *
         * @memberOf _.templateSettings
         * @type RegExp
         */
        'escape': /<%-([\s\S]+?)%>/g,
  
        /**
         * Used to detect code to be evaluated.
         *
         * @memberOf _.templateSettings
         * @type RegExp
         */
        'evaluate': /<%([\s\S]+?)%>/g,
  
        /**
         * Used to detect `data` property values to inject.
         *
         * @memberOf _.templateSettings
         * @type RegExp
         */
        'interpolate': reInterpolate,
  
        /**
         * Used to reference the data object in the template text.
         *
         * @memberOf _.templateSettings
         * @type string
         */
        'variable': '',
  
        /**
         * Used to import variables into the compiled template.
         *
         * @memberOf _.templateSettings
         * @type Object
         */
        'imports': {
  
          /**
           * A reference to the `lodash` function.
           *
           * @memberOf _.templateSettings.imports
           * @type Function
           */
          '_': lodash
        }
      };
  
      /*--------------------------------------------------------------------------*/
  
      /**
       * The base implementation of `_.bind` that creates the bound function and
       * sets its meta data.
       *
       * @private
       * @param {Array} bindData The bind data array.
       * @returns {Function} Returns the new bound function.
       */
      function baseBind(bindData) {
        var func = bindData[0],
            partialArgs = bindData[2],
            thisArg = bindData[4];
  
        function bound() {
          // `Function#bind` spec
          // http://es5.github.io/#x15.3.4.5
          if (partialArgs) {
            // avoid `arguments` object deoptimizations by using `slice` instead
            // of `Array.prototype.slice.call` and not assigning `arguments` to a
            // variable as a ternary expression
            var args = slice(partialArgs);
            push.apply(args, arguments);
          }
          // mimic the constructor's `return` behavior
          // http://es5.github.io/#x13.2.2
          if (this instanceof bound) {
            // ensure `new bound` is an instance of `func`
            var thisBinding = baseCreate(func.prototype),
                result = func.apply(thisBinding, args || arguments);
            return isObject(result) ? result : thisBinding;
          }
          return func.apply(thisArg, args || arguments);
        }
        setBindData(bound, bindData);
        return bound;
      }
  
      /**
       * The base implementation of `_.clone` without argument juggling or support
       * for `thisArg` binding.
       *
       * @private
       * @param {*} value The value to clone.
       * @param {boolean} [isDeep=false] Specify a deep clone.
       * @param {Function} [callback] The function to customize cloning values.
       * @param {Array} [stackA=[]] Tracks traversed source objects.
       * @param {Array} [stackB=[]] Associates clones with source counterparts.
       * @returns {*} Returns the cloned value.
       */
      function baseClone(value, isDeep, callback, stackA, stackB) {
        if (callback) {
          var result = callback(value);
          if (typeof result != 'undefined') {
            return result;
          }
        }
        // inspect [[Class]]
        var isObj = isObject(value);
        if (isObj) {
          var className = toString.call(value);
          if (!cloneableClasses[className]) {
            return value;
          }
          var ctor = ctorByClass[className];
          switch (className) {
            case boolClass:
            case dateClass:
              return new ctor(+value);
  
            case numberClass:
            case stringClass:
              return new ctor(value);
  
            case regexpClass:
              result = ctor(value.source, reFlags.exec(value));
              result.lastIndex = value.lastIndex;
              return result;
          }
        } else {
          return value;
        }
        var isArr = isArray(value);
        if (isDeep) {
          // check for circular references and return corresponding clone
          var initedStack = !stackA;
          stackA || (stackA = getArray());
          stackB || (stackB = getArray());
  
          var length = stackA.length;
          while (length--) {
            if (stackA[length] == value) {
              return stackB[length];
            }
          }
          result = isArr ? ctor(value.length) : {};
        }
        else {
          result = isArr ? slice(value) : assign({}, value);
        }
        // add array properties assigned by `RegExp#exec`
        if (isArr) {
          if (hasOwnProperty.call(value, 'index')) {
            result.index = value.index;
          }
          if (hasOwnProperty.call(value, 'input')) {
            result.input = value.input;
          }
        }
        // exit for shallow clone
        if (!isDeep) {
          return result;
        }
        // add the source value to the stack of traversed objects
        // and associate it with its clone
        stackA.push(value);
        stackB.push(result);
  
        // recursively populate clone (susceptible to call stack limits)
        (isArr ? forEach : forOwn)(value, function(objValue, key) {
          result[key] = baseClone(objValue, isDeep, callback, stackA, stackB);
        });
  
        if (initedStack) {
          releaseArray(stackA);
          releaseArray(stackB);
        }
        return result;
      }
  
      /**
       * The base implementation of `_.create` without support for assigning
       * properties to the created object.
       *
       * @private
       * @param {Object} prototype The object to inherit from.
       * @returns {Object} Returns the new object.
       */
      function baseCreate(prototype, properties) {
        return isObject(prototype) ? nativeCreate(prototype) : {};
      }
      // fallback for browsers without `Object.create`
      if (!nativeCreate) {
        baseCreate = (function() {
          function Object() {}
          return function(prototype) {
            if (isObject(prototype)) {
              Object.prototype = prototype;
              var result = new Object;
              Object.prototype = null;
            }
            return result || context.Object();
          };
        }());
      }
  
      /**
       * The base implementation of `_.createCallback` without support for creating
       * "_.pluck" or "_.where" style callbacks.
       *
       * @private
       * @param {*} [func=identity] The value to convert to a callback.
       * @param {*} [thisArg] The `this` binding of the created callback.
       * @param {number} [argCount] The number of arguments the callback accepts.
       * @returns {Function} Returns a callback function.
       */
      function baseCreateCallback(func, thisArg, argCount) {
        if (typeof func != 'function') {
          return identity;
        }
        // exit early for no `thisArg` or already bound by `Function#bind`
        if (typeof thisArg == 'undefined' || !('prototype' in func)) {
          return func;
        }
        var bindData = func.__bindData__;
        if (typeof bindData == 'undefined') {
          if (support.funcNames) {
            bindData = !func.name;
          }
          bindData = bindData || !support.funcDecomp;
          if (!bindData) {
            var source = fnToString.call(func);
            if (!support.funcNames) {
              bindData = !reFuncName.test(source);
            }
            if (!bindData) {
              // checks if `func` references the `this` keyword and stores the result
              bindData = reThis.test(source);
              setBindData(func, bindData);
            }
          }
        }
        // exit early if there are no `this` references or `func` is bound
        if (bindData === false || (bindData !== true && bindData[1] & 1)) {
          return func;
        }
        switch (argCount) {
          case 1: return function(value) {
            return func.call(thisArg, value);
          };
          case 2: return function(a, b) {
            return func.call(thisArg, a, b);
          };
          case 3: return function(value, index, collection) {
            return func.call(thisArg, value, index, collection);
          };
          case 4: return function(accumulator, value, index, collection) {
            return func.call(thisArg, accumulator, value, index, collection);
          };
        }
        return bind(func, thisArg);
      }
  
      /**
       * The base implementation of `createWrapper` that creates the wrapper and
       * sets its meta data.
       *
       * @private
       * @param {Array} bindData The bind data array.
       * @returns {Function} Returns the new function.
       */
      function baseCreateWrapper(bindData) {
        var func = bindData[0],
            bitmask = bindData[1],
            partialArgs = bindData[2],
            partialRightArgs = bindData[3],
            thisArg = bindData[4],
            arity = bindData[5];
  
        var isBind = bitmask & 1,
            isBindKey = bitmask & 2,
            isCurry = bitmask & 4,
            isCurryBound = bitmask & 8,
            key = func;
  
        function bound() {
          var thisBinding = isBind ? thisArg : this;
          if (partialArgs) {
            var args = slice(partialArgs);
            push.apply(args, arguments);
          }
          if (partialRightArgs || isCurry) {
            args || (args = slice(arguments));
            if (partialRightArgs) {
              push.apply(args, partialRightArgs);
            }
            if (isCurry && args.length < arity) {
              bitmask |= 16 & ~32;
              return baseCreateWrapper([func, (isCurryBound ? bitmask : bitmask & ~3), args, null, thisArg, arity]);
            }
          }
          args || (args = arguments);
          if (isBindKey) {
            func = thisBinding[key];
          }
          if (this instanceof bound) {
            thisBinding = baseCreate(func.prototype);
            var result = func.apply(thisBinding, args);
            return isObject(result) ? result : thisBinding;
          }
          return func.apply(thisBinding, args);
        }
        setBindData(bound, bindData);
        return bound;
      }
  
      /**
       * The base implementation of `_.difference` that accepts a single array
       * of values to exclude.
       *
       * @private
       * @param {Array} array The array to process.
       * @param {Array} [values] The array of values to exclude.
       * @returns {Array} Returns a new array of filtered values.
       */
      function baseDifference(array, values) {
        var index = -1,
            indexOf = getIndexOf(),
            length = array ? array.length : 0,
            isLarge = length >= largeArraySize && indexOf === baseIndexOf,
            result = [];
  
        if (isLarge) {
          var cache = createCache(values);
          if (cache) {
            indexOf = cacheIndexOf;
            values = cache;
          } else {
            isLarge = false;
          }
        }
        while (++index < length) {
          var value = array[index];
          if (indexOf(values, value) < 0) {
            result.push(value);
          }
        }
        if (isLarge) {
          releaseObject(values);
        }
        return result;
      }
  
      /**
       * The base implementation of `_.flatten` without support for callback
       * shorthands or `thisArg` binding.
       *
       * @private
       * @param {Array} array The array to flatten.
       * @param {boolean} [isShallow=false] A flag to restrict flattening to a single level.
       * @param {boolean} [isStrict=false] A flag to restrict flattening to arrays and `arguments` objects.
       * @param {number} [fromIndex=0] The index to start from.
       * @returns {Array} Returns a new flattened array.
       */
      function baseFlatten(array, isShallow, isStrict, fromIndex) {
        var index = (fromIndex || 0) - 1,
            length = array ? array.length : 0,
            result = [];
  
        while (++index < length) {
          var value = array[index];
  
          if (value && typeof value == 'object' && typeof value.length == 'number'
              && (isArray(value) || isArguments(value))) {
            // recursively flatten arrays (susceptible to call stack limits)
            if (!isShallow) {
              value = baseFlatten(value, isShallow, isStrict);
            }
            var valIndex = -1,
                valLength = value.length,
                resIndex = result.length;
  
            result.length += valLength;
            while (++valIndex < valLength) {
              result[resIndex++] = value[valIndex];
            }
          } else if (!isStrict) {
            result.push(value);
          }
        }
        return result;
      }
  
      /**
       * The base implementation of `_.isEqual`, without support for `thisArg` binding,
       * that allows partial "_.where" style comparisons.
       *
       * @private
       * @param {*} a The value to compare.
       * @param {*} b The other value to compare.
       * @param {Function} [callback] The function to customize comparing values.
       * @param {Function} [isWhere=false] A flag to indicate performing partial comparisons.
       * @param {Array} [stackA=[]] Tracks traversed `a` objects.
       * @param {Array} [stackB=[]] Tracks traversed `b` objects.
       * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
       */
      function baseIsEqual(a, b, callback, isWhere, stackA, stackB) {
        // used to indicate that when comparing objects, `a` has at least the properties of `b`
        if (callback) {
          var result = callback(a, b);
          if (typeof result != 'undefined') {
            return !!result;
          }
        }
        // exit early for identical values
        if (a === b) {
          // treat `+0` vs. `-0` as not equal
          return a !== 0 || (1 / a == 1 / b);
        }
        var type = typeof a,
            otherType = typeof b;
  
        // exit early for unlike primitive values
        if (a === a &&
            !(a && objectTypes[type]) &&
            !(b && objectTypes[otherType])) {
          return false;
        }
        // exit early for `null` and `undefined` avoiding ES3's Function#call behavior
        // http://es5.github.io/#x15.3.4.4
        if (a == null || b == null) {
          return a === b;
        }
        // compare [[Class]] names
        var className = toString.call(a),
            otherClass = toString.call(b);
  
        if (className == argsClass) {
          className = objectClass;
        }
        if (otherClass == argsClass) {
          otherClass = objectClass;
        }
        if (className != otherClass) {
          return false;
        }
        switch (className) {
          case boolClass:
          case dateClass:
            // coerce dates and booleans to numbers, dates to milliseconds and booleans
            // to `1` or `0` treating invalid dates coerced to `NaN` as not equal
            return +a == +b;
  
          case numberClass:
            // treat `NaN` vs. `NaN` as equal
            return (a != +a)
              ? b != +b
              // but treat `+0` vs. `-0` as not equal
              : (a == 0 ? (1 / a == 1 / b) : a == +b);
  
          case regexpClass:
          case stringClass:
            // coerce regexes to strings (http://es5.github.io/#x15.10.6.4)
            // treat string primitives and their corresponding object instances as equal
            return a == String(b);
        }
        var isArr = className == arrayClass;
        if (!isArr) {
          // unwrap any `lodash` wrapped values
          var aWrapped = hasOwnProperty.call(a, '__wrapped__'),
              bWrapped = hasOwnProperty.call(b, '__wrapped__');
  
          if (aWrapped || bWrapped) {
            return baseIsEqual(aWrapped ? a.__wrapped__ : a, bWrapped ? b.__wrapped__ : b, callback, isWhere, stackA, stackB);
          }
          // exit for functions and DOM nodes
          if (className != objectClass) {
            return false;
          }
          // in older versions of Opera, `arguments` objects have `Array` constructors
          var ctorA = a.constructor,
              ctorB = b.constructor;
  
          // non `Object` object instances with different constructors are not equal
          if (ctorA != ctorB &&
                !(isFunction(ctorA) && ctorA instanceof ctorA && isFunction(ctorB) && ctorB instanceof ctorB) &&
                ('constructor' in a && 'constructor' in b)
              ) {
            return false;
          }
        }
        // assume cyclic structures are equal
        // the algorithm for detecting cyclic structures is adapted from ES 5.1
        // section 15.12.3, abstract operation `JO` (http://es5.github.io/#x15.12.3)
        var initedStack = !stackA;
        stackA || (stackA = getArray());
        stackB || (stackB = getArray());
  
        var length = stackA.length;
        while (length--) {
          if (stackA[length] == a) {
            return stackB[length] == b;
          }
        }
        var size = 0;
        result = true;
  
        // add `a` and `b` to the stack of traversed objects
        stackA.push(a);
        stackB.push(b);
  
        // recursively compare objects and arrays (susceptible to call stack limits)
        if (isArr) {
          // compare lengths to determine if a deep comparison is necessary
          length = a.length;
          size = b.length;
          result = size == length;
  
          if (result || isWhere) {
            // deep compare the contents, ignoring non-numeric properties
            while (size--) {
              var index = length,
                  value = b[size];
  
              if (isWhere) {
                while (index--) {
                  if ((result = baseIsEqual(a[index], value, callback, isWhere, stackA, stackB))) {
                    break;
                  }
                }
              } else if (!(result = baseIsEqual(a[size], value, callback, isWhere, stackA, stackB))) {
                break;
              }
            }
          }
        }
        else {
          // deep compare objects using `forIn`, instead of `forOwn`, to avoid `Object.keys`
          // which, in this case, is more costly
          forIn(b, function(value, key, b) {
            if (hasOwnProperty.call(b, key)) {
              // count the number of properties.
              size++;
              // deep compare each property value.
              return (result = hasOwnProperty.call(a, key) && baseIsEqual(a[key], value, callback, isWhere, stackA, stackB));
            }
          });
  
          if (result && !isWhere) {
            // ensure both objects have the same number of properties
            forIn(a, function(value, key, a) {
              if (hasOwnProperty.call(a, key)) {
                // `size` will be `-1` if `a` has more properties than `b`
                return (result = --size > -1);
              }
            });
          }
        }
        stackA.pop();
        stackB.pop();
  
        if (initedStack) {
          releaseArray(stackA);
          releaseArray(stackB);
        }
        return result;
      }
  
      /**
       * The base implementation of `_.merge` without argument juggling or support
       * for `thisArg` binding.
       *
       * @private
       * @param {Object} object The destination object.
       * @param {Object} source The source object.
       * @param {Function} [callback] The function to customize merging properties.
       * @param {Array} [stackA=[]] Tracks traversed source objects.
       * @param {Array} [stackB=[]] Associates values with source counterparts.
       */
      function baseMerge(object, source, callback, stackA, stackB) {
        (isArray(source) ? forEach : forOwn)(source, function(source, key) {
          var found,
              isArr,
              result = source,
              value = object[key];
  
          if (source && ((isArr = isArray(source)) || isPlainObject(source))) {
            // avoid merging previously merged cyclic sources
            var stackLength = stackA.length;
            while (stackLength--) {
              if ((found = stackA[stackLength] == source)) {
                value = stackB[stackLength];
                break;
              }
            }
            if (!found) {
              var isShallow;
              if (callback) {
                result = callback(value, source);
                if ((isShallow = typeof result != 'undefined')) {
                  value = result;
                }
              }
              if (!isShallow) {
                value = isArr
                  ? (isArray(value) ? value : [])
                  : (isPlainObject(value) ? value : {});
              }
              // add `source` and associated `value` to the stack of traversed objects
              stackA.push(source);
              stackB.push(value);
  
              // recursively merge objects and arrays (susceptible to call stack limits)
              if (!isShallow) {
                baseMerge(value, source, callback, stackA, stackB);
              }
            }
          }
          else {
            if (callback) {
              result = callback(value, source);
              if (typeof result == 'undefined') {
                result = source;
              }
            }
            if (typeof result != 'undefined') {
              value = result;
            }
          }
          object[key] = value;
        });
      }
  
      /**
       * The base implementation of `_.random` without argument juggling or support
       * for returning floating-point numbers.
       *
       * @private
       * @param {number} min The minimum possible value.
       * @param {number} max The maximum possible value.
       * @returns {number} Returns a random number.
       */
      function baseRandom(min, max) {
        return min + floor(nativeRandom() * (max - min + 1));
      }
  
      /**
       * The base implementation of `_.uniq` without support for callback shorthands
       * or `thisArg` binding.
       *
       * @private
       * @param {Array} array The array to process.
       * @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted.
       * @param {Function} [callback] The function called per iteration.
       * @returns {Array} Returns a duplicate-value-free array.
       */
      function baseUniq(array, isSorted, callback) {
        var index = -1,
            indexOf = getIndexOf(),
            length = array ? array.length : 0,
            result = [];
  
        var isLarge = !isSorted && length >= largeArraySize && indexOf === baseIndexOf,
            seen = (callback || isLarge) ? getArray() : result;
  
        if (isLarge) {
          var cache = createCache(seen);
          indexOf = cacheIndexOf;
          seen = cache;
        }
        while (++index < length) {
          var value = array[index],
              computed = callback ? callback(value, index, array) : value;
  
          if (isSorted
                ? !index || seen[seen.length - 1] !== computed
                : indexOf(seen, computed) < 0
              ) {
            if (callback || isLarge) {
              seen.push(computed);
            }
            result.push(value);
          }
        }
        if (isLarge) {
          releaseArray(seen.array);
          releaseObject(seen);
        } else if (callback) {
          releaseArray(seen);
        }
        return result;
      }
  
      /**
       * Creates a function that aggregates a collection, creating an object composed
       * of keys generated from the results of running each element of the collection
       * through a callback. The given `setter` function sets the keys and values
       * of the composed object.
       *
       * @private
       * @param {Function} setter The setter function.
       * @returns {Function} Returns the new aggregator function.
       */
      function createAggregator(setter) {
        return function(collection, callback, thisArg) {
          var result = {};
          callback = lodash.createCallback(callback, thisArg, 3);
  
          var index = -1,
              length = collection ? collection.length : 0;
  
          if (typeof length == 'number') {
            while (++index < length) {
              var value = collection[index];
              setter(result, value, callback(value, index, collection), collection);
            }
          } else {
            forOwn(collection, function(value, key, collection) {
              setter(result, value, callback(value, key, collection), collection);
            });
          }
          return result;
        };
      }
  
      /**
       * Creates a function that, when called, either curries or invokes `func`
       * with an optional `this` binding and partially applied arguments.
       *
       * @private
       * @param {Function|string} func The function or method name to reference.
       * @param {number} bitmask The bitmask of method flags to compose.
       *  The bitmask may be composed of the following flags:
       *  1 - `_.bind`
       *  2 - `_.bindKey`
       *  4 - `_.curry`
       *  8 - `_.curry` (bound)
       *  16 - `_.partial`
       *  32 - `_.partialRight`
       * @param {Array} [partialArgs] An array of arguments to prepend to those
       *  provided to the new function.
       * @param {Array} [partialRightArgs] An array of arguments to append to those
       *  provided to the new function.
       * @param {*} [thisArg] The `this` binding of `func`.
       * @param {number} [arity] The arity of `func`.
       * @returns {Function} Returns the new function.
       */
      function createWrapper(func, bitmask, partialArgs, partialRightArgs, thisArg, arity) {
        var isBind = bitmask & 1,
            isBindKey = bitmask & 2,
            isCurry = bitmask & 4,
            isCurryBound = bitmask & 8,
            isPartial = bitmask & 16,
            isPartialRight = bitmask & 32;
  
        if (!isBindKey && !isFunction(func)) {
          throw new TypeError;
        }
        if (isPartial && !partialArgs.length) {
          bitmask &= ~16;
          isPartial = partialArgs = false;
        }
        if (isPartialRight && !partialRightArgs.length) {
          bitmask &= ~32;
          isPartialRight = partialRightArgs = false;
        }
        var bindData = func && func.__bindData__;
        if (bindData && bindData !== true) {
          // clone `bindData`
          bindData = slice(bindData);
          if (bindData[2]) {
            bindData[2] = slice(bindData[2]);
          }
          if (bindData[3]) {
            bindData[3] = slice(bindData[3]);
          }
          // set `thisBinding` is not previously bound
          if (isBind && !(bindData[1] & 1)) {
            bindData[4] = thisArg;
          }
          // set if previously bound but not currently (subsequent curried functions)
          if (!isBind && bindData[1] & 1) {
            bitmask |= 8;
          }
          // set curried arity if not yet set
          if (isCurry && !(bindData[1] & 4)) {
            bindData[5] = arity;
          }
          // append partial left arguments
          if (isPartial) {
            push.apply(bindData[2] || (bindData[2] = []), partialArgs);
          }
          // append partial right arguments
          if (isPartialRight) {
            unshift.apply(bindData[3] || (bindData[3] = []), partialRightArgs);
          }
          // merge flags
          bindData[1] |= bitmask;
          return createWrapper.apply(null, bindData);
        }
        // fast path for `_.bind`
        var creater = (bitmask == 1 || bitmask === 17) ? baseBind : baseCreateWrapper;
        return creater([func, bitmask, partialArgs, partialRightArgs, thisArg, arity]);
      }
  
      /**
       * Used by `escape` to convert characters to HTML entities.
       *
       * @private
       * @param {string} match The matched character to escape.
       * @returns {string} Returns the escaped character.
       */
      function escapeHtmlChar(match) {
        return htmlEscapes[match];
      }
  
      /**
       * Gets the appropriate "indexOf" function. If the `_.indexOf` method is
       * customized, this method returns the custom method, otherwise it returns
       * the `baseIndexOf` function.
       *
       * @private
       * @returns {Function} Returns the "indexOf" function.
       */
      function getIndexOf() {
        var result = (result = lodash.indexOf) === indexOf ? baseIndexOf : result;
        return result;
      }
  
      /**
       * Checks if `value` is a native function.
       *
       * @private
       * @param {*} value The value to check.
       * @returns {boolean} Returns `true` if the `value` is a native function, else `false`.
       */
      function isNative(value) {
        return typeof value == 'function' && reNative.test(value);
      }
  
      /**
       * Sets `this` binding data on a given function.
       *
       * @private
       * @param {Function} func The function to set data on.
       * @param {Array} value The data array to set.
       */
      var setBindData = !defineProperty ? noop : function(func, value) {
        descriptor.value = value;
        defineProperty(func, '__bindData__', descriptor);
      };
  
      /**
       * A fallback implementation of `isPlainObject` which checks if a given value
       * is an object created by the `Object` constructor, assuming objects created
       * by the `Object` constructor have no inherited enumerable properties and that
       * there are no `Object.prototype` extensions.
       *
       * @private
       * @param {*} value The value to check.
       * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
       */
      function shimIsPlainObject(value) {
        var ctor,
            result;
  
        // avoid non Object objects, `arguments` objects, and DOM elements
        if (!(value && toString.call(value) == objectClass) ||
            (ctor = value.constructor, isFunction(ctor) && !(ctor instanceof ctor))) {
          return false;
        }
        // In most environments an object's own properties are iterated before
        // its inherited properties. If the last iterated property is an object's
        // own property then there are no inherited enumerable properties.
        forIn(value, function(value, key) {
          result = key;
        });
        return typeof result == 'undefined' || hasOwnProperty.call(value, result);
      }
  
      /**
       * Used by `unescape` to convert HTML entities to characters.
       *
       * @private
       * @param {string} match The matched character to unescape.
       * @returns {string} Returns the unescaped character.
       */
      function unescapeHtmlChar(match) {
        return htmlUnescapes[match];
      }
  
      /*--------------------------------------------------------------------------*/
  
      /**
       * Checks if `value` is an `arguments` object.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {*} value The value to check.
       * @returns {boolean} Returns `true` if the `value` is an `arguments` object, else `false`.
       * @example
       *
       * (function() { return _.isArguments(arguments); })(1, 2, 3);
       * // => true
       *
       * _.isArguments([1, 2, 3]);
       * // => false
       */
      function isArguments(value) {
        return value && typeof value == 'object' && typeof value.length == 'number' &&
          toString.call(value) == argsClass || false;
      }
  
      /**
       * Checks if `value` is an array.
       *
       * @static
       * @memberOf _
       * @type Function
       * @category Objects
       * @param {*} value The value to check.
       * @returns {boolean} Returns `true` if the `value` is an array, else `false`.
       * @example
       *
       * (function() { return _.isArray(arguments); })();
       * // => false
       *
       * _.isArray([1, 2, 3]);
       * // => true
       */
      var isArray = nativeIsArray || function(value) {
        return value && typeof value == 'object' && typeof value.length == 'number' &&
          toString.call(value) == arrayClass || false;
      };
  
      /**
       * A fallback implementation of `Object.keys` which produces an array of the
       * given object's own enumerable property names.
       *
       * @private
       * @type Function
       * @param {Object} object The object to inspect.
       * @returns {Array} Returns an array of property names.
       */
      var shimKeys = function(object) {
        var index, iterable = object, result = [];
        if (!iterable) return result;
        if (!(objectTypes[typeof object])) return result;
          for (index in iterable) {
            if (hasOwnProperty.call(iterable, index)) {
              result.push(index);
            }
          }
        return result
      };
  
      /**
       * Creates an array composed of the own enumerable property names of an object.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {Object} object The object to inspect.
       * @returns {Array} Returns an array of property names.
       * @example
       *
       * _.keys({ 'one': 1, 'two': 2, 'three': 3 });
       * // => ['one', 'two', 'three'] (property order is not guaranteed across environments)
       */
      var keys = !nativeKeys ? shimKeys : function(object) {
        if (!isObject(object)) {
          return [];
        }
        return nativeKeys(object);
      };
  
      /**
       * Used to convert characters to HTML entities:
       *
       * Though the `>` character is escaped for symmetry, characters like `>` and `/`
       * don't require escaping in HTML and have no special meaning unless they're part
       * of a tag or an unquoted attribute value.
       * http://mathiasbynens.be/notes/ambiguous-ampersands (under "semi-related fun fact")
       */
      var htmlEscapes = {
        '&': '&amp;',
        '<': '&lt;',
        '>': '&gt;',
        '"': '&quot;',
        "'": '&#39;'
      };
  
      /** Used to convert HTML entities to characters */
      var htmlUnescapes = invert(htmlEscapes);
  
      /** Used to match HTML entities and HTML characters */
      var reEscapedHtml = RegExp('(' + keys(htmlUnescapes).join('|') + ')', 'g'),
          reUnescapedHtml = RegExp('[' + keys(htmlEscapes).join('') + ']', 'g');
  
      /*--------------------------------------------------------------------------*/
  
      /**
       * Assigns own enumerable properties of source object(s) to the destination
       * object. Subsequent sources will overwrite property assignments of previous
       * sources. If a callback is provided it will be executed to produce the
       * assigned values. The callback is bound to `thisArg` and invoked with two
       * arguments; (objectValue, sourceValue).
       *
       * @static
       * @memberOf _
       * @type Function
       * @alias extend
       * @category Objects
       * @param {Object} object The destination object.
       * @param {...Object} [source] The source objects.
       * @param {Function} [callback] The function to customize assigning values.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {Object} Returns the destination object.
       * @example
       *
       * _.assign({ 'name': 'fred' }, { 'employer': 'slate' });
       * // => { 'name': 'fred', 'employer': 'slate' }
       *
       * var defaults = _.partialRight(_.assign, function(a, b) {
       *   return typeof a == 'undefined' ? b : a;
       * });
       *
       * var object = { 'name': 'barney' };
       * defaults(object, { 'name': 'fred', 'employer': 'slate' });
       * // => { 'name': 'barney', 'employer': 'slate' }
       */
      var assign = function(object, source, guard) {
        var index, iterable = object, result = iterable;
        if (!iterable) return result;
        var args = arguments,
            argsIndex = 0,
            argsLength = typeof guard == 'number' ? 2 : args.length;
        if (argsLength > 3 && typeof args[argsLength - 2] == 'function') {
          var callback = baseCreateCallback(args[--argsLength - 1], args[argsLength--], 2);
        } else if (argsLength > 2 && typeof args[argsLength - 1] == 'function') {
          callback = args[--argsLength];
        }
        while (++argsIndex < argsLength) {
          iterable = args[argsIndex];
          if (iterable && objectTypes[typeof iterable]) {
          var ownIndex = -1,
              ownProps = objectTypes[typeof iterable] && keys(iterable),
              length = ownProps ? ownProps.length : 0;
  
          while (++ownIndex < length) {
            index = ownProps[ownIndex];
            result[index] = callback ? callback(result[index], iterable[index]) : iterable[index];
          }
          }
        }
        return result
      };
  
      /**
       * Creates a clone of `value`. If `isDeep` is `true` nested objects will also
       * be cloned, otherwise they will be assigned by reference. If a callback
       * is provided it will be executed to produce the cloned values. If the
       * callback returns `undefined` cloning will be handled by the method instead.
       * The callback is bound to `thisArg` and invoked with one argument; (value).
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {*} value The value to clone.
       * @param {boolean} [isDeep=false] Specify a deep clone.
       * @param {Function} [callback] The function to customize cloning values.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {*} Returns the cloned value.
       * @example
       *
       * var characters = [
       *   { 'name': 'barney', 'age': 36 },
       *   { 'name': 'fred',   'age': 40 }
       * ];
       *
       * var shallow = _.clone(characters);
       * shallow[0] === characters[0];
       * // => true
       *
       * var deep = _.clone(characters, true);
       * deep[0] === characters[0];
       * // => false
       *
       * _.mixin({
       *   'clone': _.partialRight(_.clone, function(value) {
       *     return _.isElement(value) ? value.cloneNode(false) : undefined;
       *   })
       * });
       *
       * var clone = _.clone(document.body);
       * clone.childNodes.length;
       * // => 0
       */
      function clone(value, isDeep, callback, thisArg) {
        // allows working with "Collections" methods without using their `index`
        // and `collection` arguments for `isDeep` and `callback`
        if (typeof isDeep != 'boolean' && isDeep != null) {
          thisArg = callback;
          callback = isDeep;
          isDeep = false;
        }
        return baseClone(value, isDeep, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 1));
      }
  
      /**
       * Creates a deep clone of `value`. If a callback is provided it will be
       * executed to produce the cloned values. If the callback returns `undefined`
       * cloning will be handled by the method instead. The callback is bound to
       * `thisArg` and invoked with one argument; (value).
       *
       * Note: This method is loosely based on the structured clone algorithm. Functions
       * and DOM nodes are **not** cloned. The enumerable properties of `arguments` objects and
       * objects created by constructors other than `Object` are cloned to plain `Object` objects.
       * See http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {*} value The value to deep clone.
       * @param {Function} [callback] The function to customize cloning values.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {*} Returns the deep cloned value.
       * @example
       *
       * var characters = [
       *   { 'name': 'barney', 'age': 36 },
       *   { 'name': 'fred',   'age': 40 }
       * ];
       *
       * var deep = _.cloneDeep(characters);
       * deep[0] === characters[0];
       * // => false
       *
       * var view = {
       *   'label': 'docs',
       *   'node': element
       * };
       *
       * var clone = _.cloneDeep(view, function(value) {
       *   return _.isElement(value) ? value.cloneNode(true) : undefined;
       * });
       *
       * clone.node == view.node;
       * // => false
       */
      function cloneDeep(value, callback, thisArg) {
        return baseClone(value, true, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 1));
      }
  
      /**
       * Creates an object that inherits from the given `prototype` object. If a
       * `properties` object is provided its own enumerable properties are assigned
       * to the created object.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {Object} prototype The object to inherit from.
       * @param {Object} [properties] The properties to assign to the object.
       * @returns {Object} Returns the new object.
       * @example
       *
       * function Shape() {
       *   this.x = 0;
       *   this.y = 0;
       * }
       *
       * function Circle() {
       *   Shape.call(this);
       * }
       *
       * Circle.prototype = _.create(Shape.prototype, { 'constructor': Circle });
       *
       * var circle = new Circle;
       * circle instanceof Circle;
       * // => true
       *
       * circle instanceof Shape;
       * // => true
       */
      function create(prototype, properties) {
        var result = baseCreate(prototype);
        return properties ? assign(result, properties) : result;
      }
  
      /**
       * Assigns own enumerable properties of source object(s) to the destination
       * object for all destination properties that resolve to `undefined`. Once a
       * property is set, additional defaults of the same property will be ignored.
       *
       * @static
       * @memberOf _
       * @type Function
       * @category Objects
       * @param {Object} object The destination object.
       * @param {...Object} [source] The source objects.
       * @param- {Object} [guard] Allows working with `_.reduce` without using its
       *  `key` and `object` arguments as sources.
       * @returns {Object} Returns the destination object.
       * @example
       *
       * var object = { 'name': 'barney' };
       * _.defaults(object, { 'name': 'fred', 'employer': 'slate' });
       * // => { 'name': 'barney', 'employer': 'slate' }
       */
      var defaults = function(object, source, guard) {
        var index, iterable = object, result = iterable;
        if (!iterable) return result;
        var args = arguments,
            argsIndex = 0,
            argsLength = typeof guard == 'number' ? 2 : args.length;
        while (++argsIndex < argsLength) {
          iterable = args[argsIndex];
          if (iterable && objectTypes[typeof iterable]) {
          var ownIndex = -1,
              ownProps = objectTypes[typeof iterable] && keys(iterable),
              length = ownProps ? ownProps.length : 0;
  
          while (++ownIndex < length) {
            index = ownProps[ownIndex];
            if (typeof result[index] == 'undefined') result[index] = iterable[index];
          }
          }
        }
        return result
      };
  
      /**
       * This method is like `_.findIndex` except that it returns the key of the
       * first element that passes the callback check, instead of the element itself.
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {Object} object The object to search.
       * @param {Function|Object|string} [callback=identity] The function called per
       *  iteration. If a property name or object is provided it will be used to
       *  create a "_.pluck" or "_.where" style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {string|undefined} Returns the key of the found element, else `undefined`.
       * @example
       *
       * var characters = {
       *   'barney': {  'age': 36, 'blocked': false },
       *   'fred': {    'age': 40, 'blocked': true },
       *   'pebbles': { 'age': 1,  'blocked': false }
       * };
       *
       * _.findKey(characters, function(chr) {
       *   return chr.age < 40;
       * });
       * // => 'barney' (property order is not guaranteed across environments)
       *
       * // using "_.where" callback shorthand
       * _.findKey(characters, { 'age': 1 });
       * // => 'pebbles'
       *
       * // using "_.pluck" callback shorthand
       * _.findKey(characters, 'blocked');
       * // => 'fred'
       */
      function findKey(object, callback, thisArg) {
        var result;
        callback = lodash.createCallback(callback, thisArg, 3);
        forOwn(object, function(value, key, object) {
          if (callback(value, key, object)) {
            result = key;
            return false;
          }
        });
        return result;
      }
  
      /**
       * This method is like `_.findKey` except that it iterates over elements
       * of a `collection` in the opposite order.
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {Object} object The object to search.
       * @param {Function|Object|string} [callback=identity] The function called per
       *  iteration. If a property name or object is provided it will be used to
       *  create a "_.pluck" or "_.where" style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {string|undefined} Returns the key of the found element, else `undefined`.
       * @example
       *
       * var characters = {
       *   'barney': {  'age': 36, 'blocked': true },
       *   'fred': {    'age': 40, 'blocked': false },
       *   'pebbles': { 'age': 1,  'blocked': true }
       * };
       *
       * _.findLastKey(characters, function(chr) {
       *   return chr.age < 40;
       * });
       * // => returns `pebbles`, assuming `_.findKey` returns `barney`
       *
       * // using "_.where" callback shorthand
       * _.findLastKey(characters, { 'age': 40 });
       * // => 'fred'
       *
       * // using "_.pluck" callback shorthand
       * _.findLastKey(characters, 'blocked');
       * // => 'pebbles'
       */
      function findLastKey(object, callback, thisArg) {
        var result;
        callback = lodash.createCallback(callback, thisArg, 3);
        forOwnRight(object, function(value, key, object) {
          if (callback(value, key, object)) {
            result = key;
            return false;
          }
        });
        return result;
      }
  
      /**
       * Iterates over own and inherited enumerable properties of an object,
       * executing the callback for each property. The callback is bound to `thisArg`
       * and invoked with three arguments; (value, key, object). Callbacks may exit
       * iteration early by explicitly returning `false`.
       *
       * @static
       * @memberOf _
       * @type Function
       * @category Objects
       * @param {Object} object The object to iterate over.
       * @param {Function} [callback=identity] The function called per iteration.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {Object} Returns `object`.
       * @example
       *
       * function Shape() {
       *   this.x = 0;
       *   this.y = 0;
       * }
       *
       * Shape.prototype.move = function(x, y) {
       *   this.x += x;
       *   this.y += y;
       * };
       *
       * _.forIn(new Shape, function(value, key) {
       *   console.log(key);
       * });
       * // => logs 'x', 'y', and 'move' (property order is not guaranteed across environments)
       */
      var forIn = function(collection, callback, thisArg) {
        var index, iterable = collection, result = iterable;
        if (!iterable) return result;
        if (!objectTypes[typeof iterable]) return result;
        callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3);
          for (index in iterable) {
            if (callback(iterable[index], index, collection) === false) return result;
          }
        return result
      };
  
      /**
       * This method is like `_.forIn` except that it iterates over elements
       * of a `collection` in the opposite order.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {Object} object The object to iterate over.
       * @param {Function} [callback=identity] The function called per iteration.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {Object} Returns `object`.
       * @example
       *
       * function Shape() {
       *   this.x = 0;
       *   this.y = 0;
       * }
       *
       * Shape.prototype.move = function(x, y) {
       *   this.x += x;
       *   this.y += y;
       * };
       *
       * _.forInRight(new Shape, function(value, key) {
       *   console.log(key);
       * });
       * // => logs 'move', 'y', and 'x' assuming `_.forIn ` logs 'x', 'y', and 'move'
       */
      function forInRight(object, callback, thisArg) {
        var pairs = [];
  
        forIn(object, function(value, key) {
          pairs.push(key, value);
        });
  
        var length = pairs.length;
        callback = baseCreateCallback(callback, thisArg, 3);
        while (length--) {
          if (callback(pairs[length--], pairs[length], object) === false) {
            break;
          }
        }
        return object;
      }
  
      /**
       * Iterates over own enumerable properties of an object, executing the callback
       * for each property. The callback is bound to `thisArg` and invoked with three
       * arguments; (value, key, object). Callbacks may exit iteration early by
       * explicitly returning `false`.
       *
       * @static
       * @memberOf _
       * @type Function
       * @category Objects
       * @param {Object} object The object to iterate over.
       * @param {Function} [callback=identity] The function called per iteration.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {Object} Returns `object`.
       * @example
       *
       * _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) {
       *   console.log(key);
       * });
       * // => logs '0', '1', and 'length' (property order is not guaranteed across environments)
       */
      var forOwn = function(collection, callback, thisArg) {
        var index, iterable = collection, result = iterable;
        if (!iterable) return result;
        if (!objectTypes[typeof iterable]) return result;
        callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3);
          var ownIndex = -1,
              ownProps = objectTypes[typeof iterable] && keys(iterable),
              length = ownProps ? ownProps.length : 0;
  
          while (++ownIndex < length) {
            index = ownProps[ownIndex];
            if (callback(iterable[index], index, collection) === false) return result;
          }
        return result
      };
  
      /**
       * This method is like `_.forOwn` except that it iterates over elements
       * of a `collection` in the opposite order.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {Object} object The object to iterate over.
       * @param {Function} [callback=identity] The function called per iteration.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {Object} Returns `object`.
       * @example
       *
       * _.forOwnRight({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) {
       *   console.log(key);
       * });
       * // => logs 'length', '1', and '0' assuming `_.forOwn` logs '0', '1', and 'length'
       */
      function forOwnRight(object, callback, thisArg) {
        var props = keys(object),
            length = props.length;
  
        callback = baseCreateCallback(callback, thisArg, 3);
        while (length--) {
          var key = props[length];
          if (callback(object[key], key, object) === false) {
            break;
          }
        }
        return object;
      }
  
      /**
       * Creates a sorted array of property names of all enumerable properties,
       * own and inherited, of `object` that have function values.
       *
       * @static
       * @memberOf _
       * @alias methods
       * @category Objects
       * @param {Object} object The object to inspect.
       * @returns {Array} Returns an array of property names that have function values.
       * @example
       *
       * _.functions(_);
       * // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...]
       */
      function functions(object) {
        var result = [];
        forIn(object, function(value, key) {
          if (isFunction(value)) {
            result.push(key);
          }
        });
        return result.sort();
      }
  
      /**
       * Checks if the specified property name exists as a direct property of `object`,
       * instead of an inherited property.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {Object} object The object to inspect.
       * @param {string} key The name of the property to check.
       * @returns {boolean} Returns `true` if key is a direct property, else `false`.
       * @example
       *
       * _.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b');
       * // => true
       */
      function has(object, key) {
        return object ? hasOwnProperty.call(object, key) : false;
      }
  
      /**
       * Creates an object composed of the inverted keys and values of the given object.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {Object} object The object to invert.
       * @returns {Object} Returns the created inverted object.
       * @example
       *
       * _.invert({ 'first': 'fred', 'second': 'barney' });
       * // => { 'fred': 'first', 'barney': 'second' }
       */
      function invert(object) {
        var index = -1,
            props = keys(object),
            length = props.length,
            result = {};
  
        while (++index < length) {
          var key = props[index];
          result[object[key]] = key;
        }
        return result;
      }
  
      /**
       * Checks if `value` is a boolean value.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {*} value The value to check.
       * @returns {boolean} Returns `true` if the `value` is a boolean value, else `false`.
       * @example
       *
       * _.isBoolean(null);
       * // => false
       */
      function isBoolean(value) {
        return value === true || value === false ||
          value && typeof value == 'object' && toString.call(value) == boolClass || false;
      }
  
      /**
       * Checks if `value` is a date.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {*} value The value to check.
       * @returns {boolean} Returns `true` if the `value` is a date, else `false`.
       * @example
       *
       * _.isDate(new Date);
       * // => true
       */
      function isDate(value) {
        return value && typeof value == 'object' && toString.call(value) == dateClass || false;
      }
  
      /**
       * Checks if `value` is a DOM element.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {*} value The value to check.
       * @returns {boolean} Returns `true` if the `value` is a DOM element, else `false`.
       * @example
       *
       * _.isElement(document.body);
       * // => true
       */
      function isElement(value) {
        return value && value.nodeType === 1 || false;
      }
  
      /**
       * Checks if `value` is empty. Arrays, strings, or `arguments` objects with a
       * length of `0` and objects with no own enumerable properties are considered
       * "empty".
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {Array|Object|string} value The value to inspect.
       * @returns {boolean} Returns `true` if the `value` is empty, else `false`.
       * @example
       *
       * _.isEmpty([1, 2, 3]);
       * // => false
       *
       * _.isEmpty({});
       * // => true
       *
       * _.isEmpty('');
       * // => true
       */
      function isEmpty(value) {
        var result = true;
        if (!value) {
          return result;
        }
        var className = toString.call(value),
            length = value.length;
  
        if ((className == arrayClass || className == stringClass || className == argsClass ) ||
            (className == objectClass && typeof length == 'number' && isFunction(value.splice))) {
          return !length;
        }
        forOwn(value, function() {
          return (result = false);
        });
        return result;
      }
  
      /**
       * Performs a deep comparison between two values to determine if they are
       * equivalent to each other. If a callback is provided it will be executed
       * to compare values. If the callback returns `undefined` comparisons will
       * be handled by the method instead. The callback is bound to `thisArg` and
       * invoked with two arguments; (a, b).
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {*} a The value to compare.
       * @param {*} b The other value to compare.
       * @param {Function} [callback] The function to customize comparing values.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
       * @example
       *
       * var object = { 'name': 'fred' };
       * var copy = { 'name': 'fred' };
       *
       * object == copy;
       * // => false
       *
       * _.isEqual(object, copy);
       * // => true
       *
       * var words = ['hello', 'goodbye'];
       * var otherWords = ['hi', 'goodbye'];
       *
       * _.isEqual(words, otherWords, function(a, b) {
       *   var reGreet = /^(?:hello|hi)$/i,
       *       aGreet = _.isString(a) && reGreet.test(a),
       *       bGreet = _.isString(b) && reGreet.test(b);
       *
       *   return (aGreet || bGreet) ? (aGreet == bGreet) : undefined;
       * });
       * // => true
       */
      function isEqual(a, b, callback, thisArg) {
        return baseIsEqual(a, b, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 2));
      }
  
      /**
       * Checks if `value` is, or can be coerced to, a finite number.
       *
       * Note: This is not the same as native `isFinite` which will return true for
       * booleans and empty strings. See http://es5.github.io/#x15.1.2.5.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {*} value The value to check.
       * @returns {boolean} Returns `true` if the `value` is finite, else `false`.
       * @example
       *
       * _.isFinite(-101);
       * // => true
       *
       * _.isFinite('10');
       * // => true
       *
       * _.isFinite(true);
       * // => false
       *
       * _.isFinite('');
       * // => false
       *
       * _.isFinite(Infinity);
       * // => false
       */
      function isFinite(value) {
        return nativeIsFinite(value) && !nativeIsNaN(parseFloat(value));
      }
  
      /**
       * Checks if `value` is a function.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {*} value The value to check.
       * @returns {boolean} Returns `true` if the `value` is a function, else `false`.
       * @example
       *
       * _.isFunction(_);
       * // => true
       */
      function isFunction(value) {
        return typeof value == 'function';
      }
  
      /**
       * Checks if `value` is the language type of Object.
       * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {*} value The value to check.
       * @returns {boolean} Returns `true` if the `value` is an object, else `false`.
       * @example
       *
       * _.isObject({});
       * // => true
       *
       * _.isObject([1, 2, 3]);
       * // => true
       *
       * _.isObject(1);
       * // => false
       */
      function isObject(value) {
        // check if the value is the ECMAScript language type of Object
        // http://es5.github.io/#x8
        // and avoid a V8 bug
        // http://code.google.com/p/v8/issues/detail?id=2291
        return !!(value && objectTypes[typeof value]);
      }
  
      /**
       * Checks if `value` is `NaN`.
       *
       * Note: This is not the same as native `isNaN` which will return `true` for
       * `undefined` and other non-numeric values. See http://es5.github.io/#x15.1.2.4.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {*} value The value to check.
       * @returns {boolean} Returns `true` if the `value` is `NaN`, else `false`.
       * @example
       *
       * _.isNaN(NaN);
       * // => true
       *
       * _.isNaN(new Number(NaN));
       * // => true
       *
       * isNaN(undefined);
       * // => true
       *
       * _.isNaN(undefined);
       * // => false
       */
      function isNaN(value) {
        // `NaN` as a primitive is the only value that is not equal to itself
        // (perform the [[Class]] check first to avoid errors with some host objects in IE)
        return isNumber(value) && value != +value;
      }
  
      /**
       * Checks if `value` is `null`.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {*} value The value to check.
       * @returns {boolean} Returns `true` if the `value` is `null`, else `false`.
       * @example
       *
       * _.isNull(null);
       * // => true
       *
       * _.isNull(undefined);
       * // => false
       */
      function isNull(value) {
        return value === null;
      }
  
      /**
       * Checks if `value` is a number.
       *
       * Note: `NaN` is considered a number. See http://es5.github.io/#x8.5.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {*} value The value to check.
       * @returns {boolean} Returns `true` if the `value` is a number, else `false`.
       * @example
       *
       * _.isNumber(8.4 * 5);
       * // => true
       */
      function isNumber(value) {
        return typeof value == 'number' ||
          value && typeof value == 'object' && toString.call(value) == numberClass || false;
      }
  
      /**
       * Checks if `value` is an object created by the `Object` constructor.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {*} value The value to check.
       * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
       * @example
       *
       * function Shape() {
       *   this.x = 0;
       *   this.y = 0;
       * }
       *
       * _.isPlainObject(new Shape);
       * // => false
       *
       * _.isPlainObject([1, 2, 3]);
       * // => false
       *
       * _.isPlainObject({ 'x': 0, 'y': 0 });
       * // => true
       */
      var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) {
        if (!(value && toString.call(value) == objectClass)) {
          return false;
        }
        var valueOf = value.valueOf,
            objProto = isNative(valueOf) && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto);
  
        return objProto
          ? (value == objProto || getPrototypeOf(value) == objProto)
          : shimIsPlainObject(value);
      };
  
      /**
       * Checks if `value` is a regular expression.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {*} value The value to check.
       * @returns {boolean} Returns `true` if the `value` is a regular expression, else `false`.
       * @example
       *
       * _.isRegExp(/fred/);
       * // => true
       */
      function isRegExp(value) {
        return value && typeof value == 'object' && toString.call(value) == regexpClass || false;
      }
  
      /**
       * Checks if `value` is a string.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {*} value The value to check.
       * @returns {boolean} Returns `true` if the `value` is a string, else `false`.
       * @example
       *
       * _.isString('fred');
       * // => true
       */
      function isString(value) {
        return typeof value == 'string' ||
          value && typeof value == 'object' && toString.call(value) == stringClass || false;
      }
  
      /**
       * Checks if `value` is `undefined`.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {*} value The value to check.
       * @returns {boolean} Returns `true` if the `value` is `undefined`, else `false`.
       * @example
       *
       * _.isUndefined(void 0);
       * // => true
       */
      function isUndefined(value) {
        return typeof value == 'undefined';
      }
  
      /**
       * Creates an object with the same keys as `object` and values generated by
       * running each own enumerable property of `object` through the callback.
       * The callback is bound to `thisArg` and invoked with three arguments;
       * (value, key, object).
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {Object} object The object to iterate over.
       * @param {Function|Object|string} [callback=identity] The function called
       *  per iteration. If a property name or object is provided it will be used
       *  to create a "_.pluck" or "_.where" style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {Array} Returns a new object with values of the results of each `callback` execution.
       * @example
       *
       * _.mapValues({ 'a': 1, 'b': 2, 'c': 3} , function(num) { return num * 3; });
       * // => { 'a': 3, 'b': 6, 'c': 9 }
       *
       * var characters = {
       *   'fred': { 'name': 'fred', 'age': 40 },
       *   'pebbles': { 'name': 'pebbles', 'age': 1 }
       * };
       *
       * // using "_.pluck" callback shorthand
       * _.mapValues(characters, 'age');
       * // => { 'fred': 40, 'pebbles': 1 }
       */
      function mapValues(object, callback, thisArg) {
        var result = {};
        callback = lodash.createCallback(callback, thisArg, 3);
  
        forOwn(object, function(value, key, object) {
          result[key] = callback(value, key, object);
        });
        return result;
      }
  
      /**
       * Recursively merges own enumerable properties of the source object(s), that
       * don't resolve to `undefined` into the destination object. Subsequent sources
       * will overwrite property assignments of previous sources. If a callback is
       * provided it will be executed to produce the merged values of the destination
       * and source properties. If the callback returns `undefined` merging will
       * be handled by the method instead. The callback is bound to `thisArg` and
       * invoked with two arguments; (objectValue, sourceValue).
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {Object} object The destination object.
       * @param {...Object} [source] The source objects.
       * @param {Function} [callback] The function to customize merging properties.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {Object} Returns the destination object.
       * @example
       *
       * var names = {
       *   'characters': [
       *     { 'name': 'barney' },
       *     { 'name': 'fred' }
       *   ]
       * };
       *
       * var ages = {
       *   'characters': [
       *     { 'age': 36 },
       *     { 'age': 40 }
       *   ]
       * };
       *
       * _.merge(names, ages);
       * // => { 'characters': [{ 'name': 'barney', 'age': 36 }, { 'name': 'fred', 'age': 40 }] }
       *
       * var food = {
       *   'fruits': ['apple'],
       *   'vegetables': ['beet']
       * };
       *
       * var otherFood = {
       *   'fruits': ['banana'],
       *   'vegetables': ['carrot']
       * };
       *
       * _.merge(food, otherFood, function(a, b) {
       *   return _.isArray(a) ? a.concat(b) : undefined;
       * });
       * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot] }
       */
      function merge(object) {
        var args = arguments,
            length = 2;
  
        if (!isObject(object)) {
          return object;
        }
        // allows working with `_.reduce` and `_.reduceRight` without using
        // their `index` and `collection` arguments
        if (typeof args[2] != 'number') {
          length = args.length;
        }
        if (length > 3 && typeof args[length - 2] == 'function') {
          var callback = baseCreateCallback(args[--length - 1], args[length--], 2);
        } else if (length > 2 && typeof args[length - 1] == 'function') {
          callback = args[--length];
        }
        var sources = slice(arguments, 1, length),
            index = -1,
            stackA = getArray(),
            stackB = getArray();
  
        while (++index < length) {
          baseMerge(object, sources[index], callback, stackA, stackB);
        }
        releaseArray(stackA);
        releaseArray(stackB);
        return object;
      }
  
      /**
       * Creates a shallow clone of `object` excluding the specified properties.
       * Property names may be specified as individual arguments or as arrays of
       * property names. If a callback is provided it will be executed for each
       * property of `object` omitting the properties the callback returns truey
       * for. The callback is bound to `thisArg` and invoked with three arguments;
       * (value, key, object).
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {Object} object The source object.
       * @param {Function|...string|string[]} [callback] The properties to omit or the
       *  function called per iteration.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {Object} Returns an object without the omitted properties.
       * @example
       *
       * _.omit({ 'name': 'fred', 'age': 40 }, 'age');
       * // => { 'name': 'fred' }
       *
       * _.omit({ 'name': 'fred', 'age': 40 }, function(value) {
       *   return typeof value == 'number';
       * });
       * // => { 'name': 'fred' }
       */
      function omit(object, callback, thisArg) {
        var result = {};
        if (typeof callback != 'function') {
          var props = [];
          forIn(object, function(value, key) {
            props.push(key);
          });
          props = baseDifference(props, baseFlatten(arguments, true, false, 1));
  
          var index = -1,
              length = props.length;
  
          while (++index < length) {
            var key = props[index];
            result[key] = object[key];
          }
        } else {
          callback = lodash.createCallback(callback, thisArg, 3);
          forIn(object, function(value, key, object) {
            if (!callback(value, key, object)) {
              result[key] = value;
            }
          });
        }
        return result;
      }
  
      /**
       * Creates a two dimensional array of an object's key-value pairs,
       * i.e. `[[key1, value1], [key2, value2]]`.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {Object} object The object to inspect.
       * @returns {Array} Returns new array of key-value pairs.
       * @example
       *
       * _.pairs({ 'barney': 36, 'fred': 40 });
       * // => [['barney', 36], ['fred', 40]] (property order is not guaranteed across environments)
       */
      function pairs(object) {
        var index = -1,
            props = keys(object),
            length = props.length,
            result = Array(length);
  
        while (++index < length) {
          var key = props[index];
          result[index] = [key, object[key]];
        }
        return result;
      }
  
      /**
       * Creates a shallow clone of `object` composed of the specified properties.
       * Property names may be specified as individual arguments or as arrays of
       * property names. If a callback is provided it will be executed for each
       * property of `object` picking the properties the callback returns truey
       * for. The callback is bound to `thisArg` and invoked with three arguments;
       * (value, key, object).
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {Object} object The source object.
       * @param {Function|...string|string[]} [callback] The function called per
       *  iteration or property names to pick, specified as individual property
       *  names or arrays of property names.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {Object} Returns an object composed of the picked properties.
       * @example
       *
       * _.pick({ 'name': 'fred', '_userid': 'fred1' }, 'name');
       * // => { 'name': 'fred' }
       *
       * _.pick({ 'name': 'fred', '_userid': 'fred1' }, function(value, key) {
       *   return key.charAt(0) != '_';
       * });
       * // => { 'name': 'fred' }
       */
      function pick(object, callback, thisArg) {
        var result = {};
        if (typeof callback != 'function') {
          var index = -1,
              props = baseFlatten(arguments, true, false, 1),
              length = isObject(object) ? props.length : 0;
  
          while (++index < length) {
            var key = props[index];
            if (key in object) {
              result[key] = object[key];
            }
          }
        } else {
          callback = lodash.createCallback(callback, thisArg, 3);
          forIn(object, function(value, key, object) {
            if (callback(value, key, object)) {
              result[key] = value;
            }
          });
        }
        return result;
      }
  
      /**
       * An alternative to `_.reduce` this method transforms `object` to a new
       * `accumulator` object which is the result of running each of its own
       * enumerable properties through a callback, with each callback execution
       * potentially mutating the `accumulator` object. The callback is bound to
       * `thisArg` and invoked with four arguments; (accumulator, value, key, object).
       * Callbacks may exit iteration early by explicitly returning `false`.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {Array|Object} object The object to iterate over.
       * @param {Function} [callback=identity] The function called per iteration.
       * @param {*} [accumulator] The custom accumulator value.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {*} Returns the accumulated value.
       * @example
       *
       * var squares = _.transform([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], function(result, num) {
       *   num *= num;
       *   if (num % 2) {
       *     return result.push(num) < 3;
       *   }
       * });
       * // => [1, 9, 25]
       *
       * var mapped = _.transform({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) {
       *   result[key] = num * 3;
       * });
       * // => { 'a': 3, 'b': 6, 'c': 9 }
       */
      function transform(object, callback, accumulator, thisArg) {
        var isArr = isArray(object);
        if (accumulator == null) {
          if (isArr) {
            accumulator = [];
          } else {
            var ctor = object && object.constructor,
                proto = ctor && ctor.prototype;
  
            accumulator = baseCreate(proto);
          }
        }
        if (callback) {
          callback = lodash.createCallback(callback, thisArg, 4);
          (isArr ? forEach : forOwn)(object, function(value, index, object) {
            return callback(accumulator, value, index, object);
          });
        }
        return accumulator;
      }
  
      /**
       * Creates an array composed of the own enumerable property values of `object`.
       *
       * @static
       * @memberOf _
       * @category Objects
       * @param {Object} object The object to inspect.
       * @returns {Array} Returns an array of property values.
       * @example
       *
       * _.values({ 'one': 1, 'two': 2, 'three': 3 });
       * // => [1, 2, 3] (property order is not guaranteed across environments)
       */
      function values(object) {
        var index = -1,
            props = keys(object),
            length = props.length,
            result = Array(length);
  
        while (++index < length) {
          result[index] = object[props[index]];
        }
        return result;
      }
  
      /*--------------------------------------------------------------------------*/
  
      /**
       * Creates an array of elements from the specified indexes, or keys, of the
       * `collection`. Indexes may be specified as individual arguments or as arrays
       * of indexes.
       *
       * @static
       * @memberOf _
       * @category Collections
       * @param {Array|Object|string} collection The collection to iterate over.
       * @param {...(number|number[]|string|string[])} [index] The indexes of `collection`
       *   to retrieve, specified as individual indexes or arrays of indexes.
       * @returns {Array} Returns a new array of elements corresponding to the
       *  provided indexes.
       * @example
       *
       * _.at(['a', 'b', 'c', 'd', 'e'], [0, 2, 4]);
       * // => ['a', 'c', 'e']
       *
       * _.at(['fred', 'barney', 'pebbles'], 0, 2);
       * // => ['fred', 'pebbles']
       */
      function at(collection) {
        var args = arguments,
            index = -1,
            props = baseFlatten(args, true, false, 1),
            length = (args[2] && args[2][args[1]] === collection) ? 1 : props.length,
            result = Array(length);
  
        while(++index < length) {
          result[index] = collection[props[index]];
        }
        return result;
      }
  
      /**
       * Checks if a given value is present in a collection using strict equality
       * for comparisons, i.e. `===`. If `fromIndex` is negative, it is used as the
       * offset from the end of the collection.
       *
       * @static
       * @memberOf _
       * @alias include
       * @category Collections
       * @param {Array|Object|string} collection The collection to iterate over.
       * @param {*} target The value to check for.
       * @param {number} [fromIndex=0] The index to search from.
       * @returns {boolean} Returns `true` if the `target` element is found, else `false`.
       * @example
       *
       * _.contains([1, 2, 3], 1);
       * // => true
       *
       * _.contains([1, 2, 3], 1, 2);
       * // => false
       *
       * _.contains({ 'name': 'fred', 'age': 40 }, 'fred');
       * // => true
       *
       * _.contains('pebbles', 'eb');
       * // => true
       */
      function contains(collection, target, fromIndex) {
        var index = -1,
            indexOf = getIndexOf(),
            length = collection ? collection.length : 0,
            result = false;
  
        fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex) || 0;
        if (isArray(collection)) {
          result = indexOf(collection, target, fromIndex) > -1;
        } else if (typeof length == 'number') {
          result = (isString(collection) ? collection.indexOf(target, fromIndex) : indexOf(collection, target, fromIndex)) > -1;
        } else {
          forOwn(collection, function(value) {
            if (++index >= fromIndex) {
              return !(result = value === target);
            }
          });
        }
        return result;
      }
  
      /**
       * Creates an object composed of keys generated from the results of running
       * each element of `collection` through the callback. The corresponding value
       * of each key is the number of times the key was returned by the callback.
       * The callback is bound to `thisArg` and invoked with three arguments;
       * (value, index|key, collection).
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @category Collections
       * @param {Array|Object|string} collection The collection to iterate over.
       * @param {Function|Object|string} [callback=identity] The function called
       *  per iteration. If a property name or object is provided it will be used
       *  to create a "_.pluck" or "_.where" style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {Object} Returns the composed aggregate object.
       * @example
       *
       * _.countBy([4.3, 6.1, 6.4], function(num) { return Math.floor(num); });
       * // => { '4': 1, '6': 2 }
       *
       * _.countBy([4.3, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
       * // => { '4': 1, '6': 2 }
       *
       * _.countBy(['one', 'two', 'three'], 'length');
       * // => { '3': 2, '5': 1 }
       */
      var countBy = createAggregator(function(result, value, key) {
        (hasOwnProperty.call(result, key) ? result[key]++ : result[key] = 1);
      });
  
      /**
       * Checks if the given callback returns truey value for **all** elements of
       * a collection. The callback is bound to `thisArg` and invoked with three
       * arguments; (value, index|key, collection).
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @alias all
       * @category Collections
       * @param {Array|Object|string} collection The collection to iterate over.
       * @param {Function|Object|string} [callback=identity] The function called
       *  per iteration. If a property name or object is provided it will be used
       *  to create a "_.pluck" or "_.where" style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {boolean} Returns `true` if all elements passed the callback check,
       *  else `false`.
       * @example
       *
       * _.every([true, 1, null, 'yes']);
       * // => false
       *
       * var characters = [
       *   { 'name': 'barney', 'age': 36 },
       *   { 'name': 'fred',   'age': 40 }
       * ];
       *
       * // using "_.pluck" callback shorthand
       * _.every(characters, 'age');
       * // => true
       *
       * // using "_.where" callback shorthand
       * _.every(characters, { 'age': 36 });
       * // => false
       */
      function every(collection, callback, thisArg) {
        var result = true;
        callback = lodash.createCallback(callback, thisArg, 3);
  
        var index = -1,
            length = collection ? collection.length : 0;
  
        if (typeof length == 'number') {
          while (++index < length) {
            if (!(result = !!callback(collection[index], index, collection))) {
              break;
            }
          }
        } else {
          forOwn(collection, function(value, index, collection) {
            return (result = !!callback(value, index, collection));
          });
        }
        return result;
      }
  
      /**
       * Iterates over elements of a collection, returning an array of all elements
       * the callback returns truey for. The callback is bound to `thisArg` and
       * invoked with three arguments; (value, index|key, collection).
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @alias select
       * @category Collections
       * @param {Array|Object|string} collection The collection to iterate over.
       * @param {Function|Object|string} [callback=identity] The function called
       *  per iteration. If a property name or object is provided it will be used
       *  to create a "_.pluck" or "_.where" style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {Array} Returns a new array of elements that passed the callback check.
       * @example
       *
       * var evens = _.filter([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
       * // => [2, 4, 6]
       *
       * var characters = [
       *   { 'name': 'barney', 'age': 36, 'blocked': false },
       *   { 'name': 'fred',   'age': 40, 'blocked': true }
       * ];
       *
       * // using "_.pluck" callback shorthand
       * _.filter(characters, 'blocked');
       * // => [{ 'name': 'fred', 'age': 40, 'blocked': true }]
       *
       * // using "_.where" callback shorthand
       * _.filter(characters, { 'age': 36 });
       * // => [{ 'name': 'barney', 'age': 36, 'blocked': false }]
       */
      function filter(collection, callback, thisArg) {
        var result = [];
        callback = lodash.createCallback(callback, thisArg, 3);
  
        var index = -1,
            length = collection ? collection.length : 0;
  
        if (typeof length == 'number') {
          while (++index < length) {
            var value = collection[index];
            if (callback(value, index, collection)) {
              result.push(value);
            }
          }
        } else {
          forOwn(collection, function(value, index, collection) {
            if (callback(value, index, collection)) {
              result.push(value);
            }
          });
        }
        return result;
      }
  
      /**
       * Iterates over elements of a collection, returning the first element that
       * the callback returns truey for. The callback is bound to `thisArg` and
       * invoked with three arguments; (value, index|key, collection).
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @alias detect, findWhere
       * @category Collections
       * @param {Array|Object|string} collection The collection to iterate over.
       * @param {Function|Object|string} [callback=identity] The function called
       *  per iteration. If a property name or object is provided it will be used
       *  to create a "_.pluck" or "_.where" style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {*} Returns the found element, else `undefined`.
       * @example
       *
       * var characters = [
       *   { 'name': 'barney',  'age': 36, 'blocked': false },
       *   { 'name': 'fred',    'age': 40, 'blocked': true },
       *   { 'name': 'pebbles', 'age': 1,  'blocked': false }
       * ];
       *
       * _.find(characters, function(chr) {
       *   return chr.age < 40;
       * });
       * // => { 'name': 'barney', 'age': 36, 'blocked': false }
       *
       * // using "_.where" callback shorthand
       * _.find(characters, { 'age': 1 });
       * // =>  { 'name': 'pebbles', 'age': 1, 'blocked': false }
       *
       * // using "_.pluck" callback shorthand
       * _.find(characters, 'blocked');
       * // => { 'name': 'fred', 'age': 40, 'blocked': true }
       */
      function find(collection, callback, thisArg) {
        callback = lodash.createCallback(callback, thisArg, 3);
  
        var index = -1,
            length = collection ? collection.length : 0;
  
        if (typeof length == 'number') {
          while (++index < length) {
            var value = collection[index];
            if (callback(value, index, collection)) {
              return value;
            }
          }
        } else {
          var result;
          forOwn(collection, function(value, index, collection) {
            if (callback(value, index, collection)) {
              result = value;
              return false;
            }
          });
          return result;
        }
      }
  
      /**
       * This method is like `_.find` except that it iterates over elements
       * of a `collection` from right to left.
       *
       * @static
       * @memberOf _
       * @category Collections
       * @param {Array|Object|string} collection The collection to iterate over.
       * @param {Function|Object|string} [callback=identity] The function called
       *  per iteration. If a property name or object is provided it will be used
       *  to create a "_.pluck" or "_.where" style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {*} Returns the found element, else `undefined`.
       * @example
       *
       * _.findLast([1, 2, 3, 4], function(num) {
       *   return num % 2 == 1;
       * });
       * // => 3
       */
      function findLast(collection, callback, thisArg) {
        var result;
        callback = lodash.createCallback(callback, thisArg, 3);
        forEachRight(collection, function(value, index, collection) {
          if (callback(value, index, collection)) {
            result = value;
            return false;
          }
        });
        return result;
      }
  
      /**
       * Iterates over elements of a collection, executing the callback for each
       * element. The callback is bound to `thisArg` and invoked with three arguments;
       * (value, index|key, collection). Callbacks may exit iteration early by
       * explicitly returning `false`.
       *
       * Note: As with other "Collections" methods, objects with a `length` property
       * are iterated like arrays. To avoid this behavior `_.forIn` or `_.forOwn`
       * may be used for object iteration.
       *
       * @static
       * @memberOf _
       * @alias each
       * @category Collections
       * @param {Array|Object|string} collection The collection to iterate over.
       * @param {Function} [callback=identity] The function called per iteration.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {Array|Object|string} Returns `collection`.
       * @example
       *
       * _([1, 2, 3]).forEach(function(num) { console.log(num); }).join(',');
       * // => logs each number and returns '1,2,3'
       *
       * _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { console.log(num); });
       * // => logs each number and returns the object (property order is not guaranteed across environments)
       */
      function forEach(collection, callback, thisArg) {
        var index = -1,
            length = collection ? collection.length : 0;
  
        callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3);
        if (typeof length == 'number') {
          while (++index < length) {
            if (callback(collection[index], index, collection) === false) {
              break;
            }
          }
        } else {
          forOwn(collection, callback);
        }
        return collection;
      }
  
      /**
       * This method is like `_.forEach` except that it iterates over elements
       * of a `collection` from right to left.
       *
       * @static
       * @memberOf _
       * @alias eachRight
       * @category Collections
       * @param {Array|Object|string} collection The collection to iterate over.
       * @param {Function} [callback=identity] The function called per iteration.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {Array|Object|string} Returns `collection`.
       * @example
       *
       * _([1, 2, 3]).forEachRight(function(num) { console.log(num); }).join(',');
       * // => logs each number from right to left and returns '3,2,1'
       */
      function forEachRight(collection, callback, thisArg) {
        var length = collection ? collection.length : 0;
        callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3);
        if (typeof length == 'number') {
          while (length--) {
            if (callback(collection[length], length, collection) === false) {
              break;
            }
          }
        } else {
          var props = keys(collection);
          length = props.length;
          forOwn(collection, function(value, key, collection) {
            key = props ? props[--length] : --length;
            return callback(collection[key], key, collection);
          });
        }
        return collection;
      }
  
      /**
       * Creates an object composed of keys generated from the results of running
       * each element of a collection through the callback. The corresponding value
       * of each key is an array of the elements responsible for generating the key.
       * The callback is bound to `thisArg` and invoked with three arguments;
       * (value, index|key, collection).
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`
       *
       * @static
       * @memberOf _
       * @category Collections
       * @param {Array|Object|string} collection The collection to iterate over.
       * @param {Function|Object|string} [callback=identity] The function called
       *  per iteration. If a property name or object is provided it will be used
       *  to create a "_.pluck" or "_.where" style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {Object} Returns the composed aggregate object.
       * @example
       *
       * _.groupBy([4.2, 6.1, 6.4], function(num) { return Math.floor(num); });
       * // => { '4': [4.2], '6': [6.1, 6.4] }
       *
       * _.groupBy([4.2, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
       * // => { '4': [4.2], '6': [6.1, 6.4] }
       *
       * // using "_.pluck" callback shorthand
       * _.groupBy(['one', 'two', 'three'], 'length');
       * // => { '3': ['one', 'two'], '5': ['three'] }
       */
      var groupBy = createAggregator(function(result, value, key) {
        (hasOwnProperty.call(result, key) ? result[key] : result[key] = []).push(value);
      });
  
      /**
       * Creates an object composed of keys generated from the results of running
       * each element of the collection through the given callback. The corresponding
       * value of each key is the last element responsible for generating the key.
       * The callback is bound to `thisArg` and invoked with three arguments;
       * (value, index|key, collection).
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @category Collections
       * @param {Array|Object|string} collection The collection to iterate over.
       * @param {Function|Object|string} [callback=identity] The function called
       *  per iteration. If a property name or object is provided it will be used
       *  to create a "_.pluck" or "_.where" style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {Object} Returns the composed aggregate object.
       * @example
       *
       * var keys = [
       *   { 'dir': 'left', 'code': 97 },
       *   { 'dir': 'right', 'code': 100 }
       * ];
       *
       * _.indexBy(keys, 'dir');
       * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } }
       *
       * _.indexBy(keys, function(key) { return String.fromCharCode(key.code); });
       * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
       *
       * _.indexBy(characters, function(key) { this.fromCharCode(key.code); }, String);
       * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
       */
      var indexBy = createAggregator(function(result, value, key) {
        result[key] = value;
      });
  
      /**
       * Invokes the method named by `methodName` on each element in the `collection`
       * returning an array of the results of each invoked method. Additional arguments
       * will be provided to each invoked method. If `methodName` is a function it
       * will be invoked for, and `this` bound to, each element in the `collection`.
       *
       * @static
       * @memberOf _
       * @category Collections
       * @param {Array|Object|string} collection The collection to iterate over.
       * @param {Function|string} methodName The name of the method to invoke or
       *  the function invoked per iteration.
       * @param {...*} [arg] Arguments to invoke the method with.
       * @returns {Array} Returns a new array of the results of each invoked method.
       * @example
       *
       * _.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
       * // => [[1, 5, 7], [1, 2, 3]]
       *
       * _.invoke([123, 456], String.prototype.split, '');
       * // => [['1', '2', '3'], ['4', '5', '6']]
       */
      function invoke(collection, methodName) {
        var args = slice(arguments, 2),
            index = -1,
            isFunc = typeof methodName == 'function',
            length = collection ? collection.length : 0,
            result = Array(typeof length == 'number' ? length : 0);
  
        forEach(collection, function(value) {
          result[++index] = (isFunc ? methodName : value[methodName]).apply(value, args);
        });
        return result;
      }
  
      /**
       * Creates an array of values by running each element in the collection
       * through the callback. The callback is bound to `thisArg` and invoked with
       * three arguments; (value, index|key, collection).
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @alias collect
       * @category Collections
       * @param {Array|Object|string} collection The collection to iterate over.
       * @param {Function|Object|string} [callback=identity] The function called
       *  per iteration. If a property name or object is provided it will be used
       *  to create a "_.pluck" or "_.where" style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {Array} Returns a new array of the results of each `callback` execution.
       * @example
       *
       * _.map([1, 2, 3], function(num) { return num * 3; });
       * // => [3, 6, 9]
       *
       * _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; });
       * // => [3, 6, 9] (property order is not guaranteed across environments)
       *
       * var characters = [
       *   { 'name': 'barney', 'age': 36 },
       *   { 'name': 'fred',   'age': 40 }
       * ];
       *
       * // using "_.pluck" callback shorthand
       * _.map(characters, 'name');
       * // => ['barney', 'fred']
       */
      function map(collection, callback, thisArg) {
        var index = -1,
            length = collection ? collection.length : 0;
  
        callback = lodash.createCallback(callback, thisArg, 3);
        if (typeof length == 'number') {
          var result = Array(length);
          while (++index < length) {
            result[index] = callback(collection[index], index, collection);
          }
        } else {
          result = [];
          forOwn(collection, function(value, key, collection) {
            result[++index] = callback(value, key, collection);
          });
        }
        return result;
      }
  
      /**
       * Retrieves the maximum value of a collection. If the collection is empty or
       * falsey `-Infinity` is returned. If a callback is provided it will be executed
       * for each value in the collection to generate the criterion by which the value
       * is ranked. The callback is bound to `thisArg` and invoked with three
       * arguments; (value, index, collection).
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @category Collections
       * @param {Array|Object|string} collection The collection to iterate over.
       * @param {Function|Object|string} [callback=identity] The function called
       *  per iteration. If a property name or object is provided it will be used
       *  to create a "_.pluck" or "_.where" style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {*} Returns the maximum value.
       * @example
       *
       * _.max([4, 2, 8, 6]);
       * // => 8
       *
       * var characters = [
       *   { 'name': 'barney', 'age': 36 },
       *   { 'name': 'fred',   'age': 40 }
       * ];
       *
       * _.max(characters, function(chr) { return chr.age; });
       * // => { 'name': 'fred', 'age': 40 };
       *
       * // using "_.pluck" callback shorthand
       * _.max(characters, 'age');
       * // => { 'name': 'fred', 'age': 40 };
       */
      function max(collection, callback, thisArg) {
        var computed = -Infinity,
            result = computed;
  
        // allows working with functions like `_.map` without using
        // their `index` argument as a callback
        if (typeof callback != 'function' && thisArg && thisArg[callback] === collection) {
          callback = null;
        }
        if (callback == null && isArray(collection)) {
          var index = -1,
              length = collection.length;
  
          while (++index < length) {
            var value = collection[index];
            if (value > result) {
              result = value;
            }
          }
        } else {
          callback = (callback == null && isString(collection))
            ? charAtCallback
            : lodash.createCallback(callback, thisArg, 3);
  
          forEach(collection, function(value, index, collection) {
            var current = callback(value, index, collection);
            if (current > computed) {
              computed = current;
              result = value;
            }
          });
        }
        return result;
      }
  
      /**
       * Retrieves the minimum value of a collection. If the collection is empty or
       * falsey `Infinity` is returned. If a callback is provided it will be executed
       * for each value in the collection to generate the criterion by which the value
       * is ranked. The callback is bound to `thisArg` and invoked with three
       * arguments; (value, index, collection).
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @category Collections
       * @param {Array|Object|string} collection The collection to iterate over.
       * @param {Function|Object|string} [callback=identity] The function called
       *  per iteration. If a property name or object is provided it will be used
       *  to create a "_.pluck" or "_.where" style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {*} Returns the minimum value.
       * @example
       *
       * _.min([4, 2, 8, 6]);
       * // => 2
       *
       * var characters = [
       *   { 'name': 'barney', 'age': 36 },
       *   { 'name': 'fred',   'age': 40 }
       * ];
       *
       * _.min(characters, function(chr) { return chr.age; });
       * // => { 'name': 'barney', 'age': 36 };
       *
       * // using "_.pluck" callback shorthand
       * _.min(characters, 'age');
       * // => { 'name': 'barney', 'age': 36 };
       */
      function min(collection, callback, thisArg) {
        var computed = Infinity,
            result = computed;
  
        // allows working with functions like `_.map` without using
        // their `index` argument as a callback
        if (typeof callback != 'function' && thisArg && thisArg[callback] === collection) {
          callback = null;
        }
        if (callback == null && isArray(collection)) {
          var index = -1,
              length = collection.length;
  
          while (++index < length) {
            var value = collection[index];
            if (value < result) {
              result = value;
            }
          }
        } else {
          callback = (callback == null && isString(collection))
            ? charAtCallback
            : lodash.createCallback(callback, thisArg, 3);
  
          forEach(collection, function(value, index, collection) {
            var current = callback(value, index, collection);
            if (current < computed) {
              computed = current;
              result = value;
            }
          });
        }
        return result;
      }
  
      /**
       * Retrieves the value of a specified property from all elements in the collection.
       *
       * @static
       * @memberOf _
       * @type Function
       * @category Collections
       * @param {Array|Object|string} collection The collection to iterate over.
       * @param {string} property The name of the property to pluck.
       * @returns {Array} Returns a new array of property values.
       * @example
       *
       * var characters = [
       *   { 'name': 'barney', 'age': 36 },
       *   { 'name': 'fred',   'age': 40 }
       * ];
       *
       * _.pluck(characters, 'name');
       * // => ['barney', 'fred']
       */
      var pluck = map;
  
      /**
       * Reduces a collection to a value which is the accumulated result of running
       * each element in the collection through the callback, where each successive
       * callback execution consumes the return value of the previous execution. If
       * `accumulator` is not provided the first element of the collection will be
       * used as the initial `accumulator` value. The callback is bound to `thisArg`
       * and invoked with four arguments; (accumulator, value, index|key, collection).
       *
       * @static
       * @memberOf _
       * @alias foldl, inject
       * @category Collections
       * @param {Array|Object|string} collection The collection to iterate over.
       * @param {Function} [callback=identity] The function called per iteration.
       * @param {*} [accumulator] Initial value of the accumulator.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {*} Returns the accumulated value.
       * @example
       *
       * var sum = _.reduce([1, 2, 3], function(sum, num) {
       *   return sum + num;
       * });
       * // => 6
       *
       * var mapped = _.reduce({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) {
       *   result[key] = num * 3;
       *   return result;
       * }, {});
       * // => { 'a': 3, 'b': 6, 'c': 9 }
       */
      function reduce(collection, callback, accumulator, thisArg) {
        if (!collection) return accumulator;
        var noaccum = arguments.length < 3;
        callback = lodash.createCallback(callback, thisArg, 4);
  
        var index = -1,
            length = collection.length;
  
        if (typeof length == 'number') {
          if (noaccum) {
            accumulator = collection[++index];
          }
          while (++index < length) {
            accumulator = callback(accumulator, collection[index], index, collection);
          }
        } else {
          forOwn(collection, function(value, index, collection) {
            accumulator = noaccum
              ? (noaccum = false, value)
              : callback(accumulator, value, index, collection)
          });
        }
        return accumulator;
      }
  
      /**
       * This method is like `_.reduce` except that it iterates over elements
       * of a `collection` from right to left.
       *
       * @static
       * @memberOf _
       * @alias foldr
       * @category Collections
       * @param {Array|Object|string} collection The collection to iterate over.
       * @param {Function} [callback=identity] The function called per iteration.
       * @param {*} [accumulator] Initial value of the accumulator.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {*} Returns the accumulated value.
       * @example
       *
       * var list = [[0, 1], [2, 3], [4, 5]];
       * var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);
       * // => [4, 5, 2, 3, 0, 1]
       */
      function reduceRight(collection, callback, accumulator, thisArg) {
        var noaccum = arguments.length < 3;
        callback = lodash.createCallback(callback, thisArg, 4);
        forEachRight(collection, function(value, index, collection) {
          accumulator = noaccum
            ? (noaccum = false, value)
            : callback(accumulator, value, index, collection);
        });
        return accumulator;
      }
  
      /**
       * The opposite of `_.filter` this method returns the elements of a
       * collection that the callback does **not** return truey for.
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @category Collections
       * @param {Array|Object|string} collection The collection to iterate over.
       * @param {Function|Object|string} [callback=identity] The function called
       *  per iteration. If a property name or object is provided it will be used
       *  to create a "_.pluck" or "_.where" style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {Array} Returns a new array of elements that failed the callback check.
       * @example
       *
       * var odds = _.reject([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
       * // => [1, 3, 5]
       *
       * var characters = [
       *   { 'name': 'barney', 'age': 36, 'blocked': false },
       *   { 'name': 'fred',   'age': 40, 'blocked': true }
       * ];
       *
       * // using "_.pluck" callback shorthand
       * _.reject(characters, 'blocked');
       * // => [{ 'name': 'barney', 'age': 36, 'blocked': false }]
       *
       * // using "_.where" callback shorthand
       * _.reject(characters, { 'age': 36 });
       * // => [{ 'name': 'fred', 'age': 40, 'blocked': true }]
       */
      function reject(collection, callback, thisArg) {
        callback = lodash.createCallback(callback, thisArg, 3);
        return filter(collection, function(value, index, collection) {
          return !callback(value, index, collection);
        });
      }
  
      /**
       * Retrieves a random element or `n` random elements from a collection.
       *
       * @static
       * @memberOf _
       * @category Collections
       * @param {Array|Object|string} collection The collection to sample.
       * @param {number} [n] The number of elements to sample.
       * @param- {Object} [guard] Allows working with functions like `_.map`
       *  without using their `index` arguments as `n`.
       * @returns {Array} Returns the random sample(s) of `collection`.
       * @example
       *
       * _.sample([1, 2, 3, 4]);
       * // => 2
       *
       * _.sample([1, 2, 3, 4], 2);
       * // => [3, 1]
       */
      function sample(collection, n, guard) {
        if (collection && typeof collection.length != 'number') {
          collection = values(collection);
        }
        if (n == null || guard) {
          return collection ? collection[baseRandom(0, collection.length - 1)] : undefined;
        }
        var result = shuffle(collection);
        result.length = nativeMin(nativeMax(0, n), result.length);
        return result;
      }
  
      /**
       * Creates an array of shuffled values, using a version of the Fisher-Yates
       * shuffle. See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle.
       *
       * @static
       * @memberOf _
       * @category Collections
       * @param {Array|Object|string} collection The collection to shuffle.
       * @returns {Array} Returns a new shuffled collection.
       * @example
       *
       * _.shuffle([1, 2, 3, 4, 5, 6]);
       * // => [4, 1, 6, 3, 5, 2]
       */
      function shuffle(collection) {
        var index = -1,
            length = collection ? collection.length : 0,
            result = Array(typeof length == 'number' ? length : 0);
  
        forEach(collection, function(value) {
          var rand = baseRandom(0, ++index);
          result[index] = result[rand];
          result[rand] = value;
        });
        return result;
      }
  
      /**
       * Gets the size of the `collection` by returning `collection.length` for arrays
       * and array-like objects or the number of own enumerable properties for objects.
       *
       * @static
       * @memberOf _
       * @category Collections
       * @param {Array|Object|string} collection The collection to inspect.
       * @returns {number} Returns `collection.length` or number of own enumerable properties.
       * @example
       *
       * _.size([1, 2]);
       * // => 2
       *
       * _.size({ 'one': 1, 'two': 2, 'three': 3 });
       * // => 3
       *
       * _.size('pebbles');
       * // => 7
       */
      function size(collection) {
        var length = collection ? collection.length : 0;
        return typeof length == 'number' ? length : keys(collection).length;
      }
  
      /**
       * Checks if the callback returns a truey value for **any** element of a
       * collection. The function returns as soon as it finds a passing value and
       * does not iterate over the entire collection. The callback is bound to
       * `thisArg` and invoked with three arguments; (value, index|key, collection).
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @alias any
       * @category Collections
       * @param {Array|Object|string} collection The collection to iterate over.
       * @param {Function|Object|string} [callback=identity] The function called
       *  per iteration. If a property name or object is provided it will be used
       *  to create a "_.pluck" or "_.where" style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {boolean} Returns `true` if any element passed the callback check,
       *  else `false`.
       * @example
       *
       * _.some([null, 0, 'yes', false], Boolean);
       * // => true
       *
       * var characters = [
       *   { 'name': 'barney', 'age': 36, 'blocked': false },
       *   { 'name': 'fred',   'age': 40, 'blocked': true }
       * ];
       *
       * // using "_.pluck" callback shorthand
       * _.some(characters, 'blocked');
       * // => true
       *
       * // using "_.where" callback shorthand
       * _.some(characters, { 'age': 1 });
       * // => false
       */
      function some(collection, callback, thisArg) {
        var result;
        callback = lodash.createCallback(callback, thisArg, 3);
  
        var index = -1,
            length = collection ? collection.length : 0;
  
        if (typeof length == 'number') {
          while (++index < length) {
            if ((result = callback(collection[index], index, collection))) {
              break;
            }
          }
        } else {
          forOwn(collection, function(value, index, collection) {
            return !(result = callback(value, index, collection));
          });
        }
        return !!result;
      }
  
      /**
       * Creates an array of elements, sorted in ascending order by the results of
       * running each element in a collection through the callback. This method
       * performs a stable sort, that is, it will preserve the original sort order
       * of equal elements. The callback is bound to `thisArg` and invoked with
       * three arguments; (value, index|key, collection).
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an array of property names is provided for `callback` the collection
       * will be sorted by each property value.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @category Collections
       * @param {Array|Object|string} collection The collection to iterate over.
       * @param {Array|Function|Object|string} [callback=identity] The function called
       *  per iteration. If a property name or object is provided it will be used
       *  to create a "_.pluck" or "_.where" style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {Array} Returns a new array of sorted elements.
       * @example
       *
       * _.sortBy([1, 2, 3], function(num) { return Math.sin(num); });
       * // => [3, 1, 2]
       *
       * _.sortBy([1, 2, 3], function(num) { return this.sin(num); }, Math);
       * // => [3, 1, 2]
       *
       * var characters = [
       *   { 'name': 'barney',  'age': 36 },
       *   { 'name': 'fred',    'age': 40 },
       *   { 'name': 'barney',  'age': 26 },
       *   { 'name': 'fred',    'age': 30 }
       * ];
       *
       * // using "_.pluck" callback shorthand
       * _.map(_.sortBy(characters, 'age'), _.values);
       * // => [['barney', 26], ['fred', 30], ['barney', 36], ['fred', 40]]
       *
       * // sorting by multiple properties
       * _.map(_.sortBy(characters, ['name', 'age']), _.values);
       * // = > [['barney', 26], ['barney', 36], ['fred', 30], ['fred', 40]]
       */
      function sortBy(collection, callback, thisArg) {
        var index = -1,
            isArr = isArray(callback),
            length = collection ? collection.length : 0,
            result = Array(typeof length == 'number' ? length : 0);
  
        if (!isArr) {
          callback = lodash.createCallback(callback, thisArg, 3);
        }
        forEach(collection, function(value, key, collection) {
          var object = result[++index] = getObject();
          if (isArr) {
            object.criteria = map(callback, function(key) { return value[key]; });
          } else {
            (object.criteria = getArray())[0] = callback(value, key, collection);
          }
          object.index = index;
          object.value = value;
        });
  
        length = result.length;
        result.sort(compareAscending);
        while (length--) {
          var object = result[length];
          result[length] = object.value;
          if (!isArr) {
            releaseArray(object.criteria);
          }
          releaseObject(object);
        }
        return result;
      }
  
      /**
       * Converts the `collection` to an array.
       *
       * @static
       * @memberOf _
       * @category Collections
       * @param {Array|Object|string} collection The collection to convert.
       * @returns {Array} Returns the new converted array.
       * @example
       *
       * (function() { return _.toArray(arguments).slice(1); })(1, 2, 3, 4);
       * // => [2, 3, 4]
       */
      function toArray(collection) {
        if (collection && typeof collection.length == 'number') {
          return slice(collection);
        }
        return values(collection);
      }
  
      /**
       * Performs a deep comparison of each element in a `collection` to the given
       * `properties` object, returning an array of all elements that have equivalent
       * property values.
       *
       * @static
       * @memberOf _
       * @type Function
       * @category Collections
       * @param {Array|Object|string} collection The collection to iterate over.
       * @param {Object} props The object of property values to filter by.
       * @returns {Array} Returns a new array of elements that have the given properties.
       * @example
       *
       * var characters = [
       *   { 'name': 'barney', 'age': 36, 'pets': ['hoppy'] },
       *   { 'name': 'fred',   'age': 40, 'pets': ['baby puss', 'dino'] }
       * ];
       *
       * _.where(characters, { 'age': 36 });
       * // => [{ 'name': 'barney', 'age': 36, 'pets': ['hoppy'] }]
       *
       * _.where(characters, { 'pets': ['dino'] });
       * // => [{ 'name': 'fred', 'age': 40, 'pets': ['baby puss', 'dino'] }]
       */
      var where = filter;
  
      /*--------------------------------------------------------------------------*/
  
      /**
       * Creates an array with all falsey values removed. The values `false`, `null`,
       * `0`, `""`, `undefined`, and `NaN` are all falsey.
       *
       * @static
       * @memberOf _
       * @category Arrays
       * @param {Array} array The array to compact.
       * @returns {Array} Returns a new array of filtered values.
       * @example
       *
       * _.compact([0, 1, false, 2, '', 3]);
       * // => [1, 2, 3]
       */
      function compact(array) {
        var index = -1,
            length = array ? array.length : 0,
            result = [];
  
        while (++index < length) {
          var value = array[index];
          if (value) {
            result.push(value);
          }
        }
        return result;
      }
  
      /**
       * Creates an array excluding all values of the provided arrays using strict
       * equality for comparisons, i.e. `===`.
       *
       * @static
       * @memberOf _
       * @category Arrays
       * @param {Array} array The array to process.
       * @param {...Array} [values] The arrays of values to exclude.
       * @returns {Array} Returns a new array of filtered values.
       * @example
       *
       * _.difference([1, 2, 3, 4, 5], [5, 2, 10]);
       * // => [1, 3, 4]
       */
      function difference(array) {
        return baseDifference(array, baseFlatten(arguments, true, true, 1));
      }
  
      /**
       * This method is like `_.find` except that it returns the index of the first
       * element that passes the callback check, instead of the element itself.
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @category Arrays
       * @param {Array} array The array to search.
       * @param {Function|Object|string} [callback=identity] The function called
       *  per iteration. If a property name or object is provided it will be used
       *  to create a "_.pluck" or "_.where" style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {number} Returns the index of the found element, else `-1`.
       * @example
       *
       * var characters = [
       *   { 'name': 'barney',  'age': 36, 'blocked': false },
       *   { 'name': 'fred',    'age': 40, 'blocked': true },
       *   { 'name': 'pebbles', 'age': 1,  'blocked': false }
       * ];
       *
       * _.findIndex(characters, function(chr) {
       *   return chr.age < 20;
       * });
       * // => 2
       *
       * // using "_.where" callback shorthand
       * _.findIndex(characters, { 'age': 36 });
       * // => 0
       *
       * // using "_.pluck" callback shorthand
       * _.findIndex(characters, 'blocked');
       * // => 1
       */
      function findIndex(array, callback, thisArg) {
        var index = -1,
            length = array ? array.length : 0;
  
        callback = lodash.createCallback(callback, thisArg, 3);
        while (++index < length) {
          if (callback(array[index], index, array)) {
            return index;
          }
        }
        return -1;
      }
  
      /**
       * This method is like `_.findIndex` except that it iterates over elements
       * of a `collection` from right to left.
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @category Arrays
       * @param {Array} array The array to search.
       * @param {Function|Object|string} [callback=identity] The function called
       *  per iteration. If a property name or object is provided it will be used
       *  to create a "_.pluck" or "_.where" style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {number} Returns the index of the found element, else `-1`.
       * @example
       *
       * var characters = [
       *   { 'name': 'barney',  'age': 36, 'blocked': true },
       *   { 'name': 'fred',    'age': 40, 'blocked': false },
       *   { 'name': 'pebbles', 'age': 1,  'blocked': true }
       * ];
       *
       * _.findLastIndex(characters, function(chr) {
       *   return chr.age > 30;
       * });
       * // => 1
       *
       * // using "_.where" callback shorthand
       * _.findLastIndex(characters, { 'age': 36 });
       * // => 0
       *
       * // using "_.pluck" callback shorthand
       * _.findLastIndex(characters, 'blocked');
       * // => 2
       */
      function findLastIndex(array, callback, thisArg) {
        var length = array ? array.length : 0;
        callback = lodash.createCallback(callback, thisArg, 3);
        while (length--) {
          if (callback(array[length], length, array)) {
            return length;
          }
        }
        return -1;
      }
  
      /**
       * Gets the first element or first `n` elements of an array. If a callback
       * is provided elements at the beginning of the array are returned as long
       * as the callback returns truey. The callback is bound to `thisArg` and
       * invoked with three arguments; (value, index, array).
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @alias head, take
       * @category Arrays
       * @param {Array} array The array to query.
       * @param {Function|Object|number|string} [callback] The function called
       *  per element or the number of elements to return. If a property name or
       *  object is provided it will be used to create a "_.pluck" or "_.where"
       *  style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {*} Returns the first element(s) of `array`.
       * @example
       *
       * _.first([1, 2, 3]);
       * // => 1
       *
       * _.first([1, 2, 3], 2);
       * // => [1, 2]
       *
       * _.first([1, 2, 3], function(num) {
       *   return num < 3;
       * });
       * // => [1, 2]
       *
       * var characters = [
       *   { 'name': 'barney',  'blocked': true,  'employer': 'slate' },
       *   { 'name': 'fred',    'blocked': false, 'employer': 'slate' },
       *   { 'name': 'pebbles', 'blocked': true,  'employer': 'na' }
       * ];
       *
       * // using "_.pluck" callback shorthand
       * _.first(characters, 'blocked');
       * // => [{ 'name': 'barney', 'blocked': true, 'employer': 'slate' }]
       *
       * // using "_.where" callback shorthand
       * _.pluck(_.first(characters, { 'employer': 'slate' }), 'name');
       * // => ['barney', 'fred']
       */
      function first(array, callback, thisArg) {
        var n = 0,
            length = array ? array.length : 0;
  
        if (typeof callback != 'number' && callback != null) {
          var index = -1;
          callback = lodash.createCallback(callback, thisArg, 3);
          while (++index < length && callback(array[index], index, array)) {
            n++;
          }
        } else {
          n = callback;
          if (n == null || thisArg) {
            return array ? array[0] : undefined;
          }
        }
        return slice(array, 0, nativeMin(nativeMax(0, n), length));
      }
  
      /**
       * Flattens a nested array (the nesting can be to any depth). If `isShallow`
       * is truey, the array will only be flattened a single level. If a callback
       * is provided each element of the array is passed through the callback before
       * flattening. The callback is bound to `thisArg` and invoked with three
       * arguments; (value, index, array).
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @category Arrays
       * @param {Array} array The array to flatten.
       * @param {boolean} [isShallow=false] A flag to restrict flattening to a single level.
       * @param {Function|Object|string} [callback=identity] The function called
       *  per iteration. If a property name or object is provided it will be used
       *  to create a "_.pluck" or "_.where" style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {Array} Returns a new flattened array.
       * @example
       *
       * _.flatten([1, [2], [3, [[4]]]]);
       * // => [1, 2, 3, 4];
       *
       * _.flatten([1, [2], [3, [[4]]]], true);
       * // => [1, 2, 3, [[4]]];
       *
       * var characters = [
       *   { 'name': 'barney', 'age': 30, 'pets': ['hoppy'] },
       *   { 'name': 'fred',   'age': 40, 'pets': ['baby puss', 'dino'] }
       * ];
       *
       * // using "_.pluck" callback shorthand
       * _.flatten(characters, 'pets');
       * // => ['hoppy', 'baby puss', 'dino']
       */
      function flatten(array, isShallow, callback, thisArg) {
        // juggle arguments
        if (typeof isShallow != 'boolean' && isShallow != null) {
          thisArg = callback;
          callback = (typeof isShallow != 'function' && thisArg && thisArg[isShallow] === array) ? null : isShallow;
          isShallow = false;
        }
        if (callback != null) {
          array = map(array, callback, thisArg);
        }
        return baseFlatten(array, isShallow);
      }
  
      /**
       * Gets the index at which the first occurrence of `value` is found using
       * strict equality for comparisons, i.e. `===`. If the array is already sorted
       * providing `true` for `fromIndex` will run a faster binary search.
       *
       * @static
       * @memberOf _
       * @category Arrays
       * @param {Array} array The array to search.
       * @param {*} value The value to search for.
       * @param {boolean|number} [fromIndex=0] The index to search from or `true`
       *  to perform a binary search on a sorted array.
       * @returns {number} Returns the index of the matched value or `-1`.
       * @example
       *
       * _.indexOf([1, 2, 3, 1, 2, 3], 2);
       * // => 1
       *
       * _.indexOf([1, 2, 3, 1, 2, 3], 2, 3);
       * // => 4
       *
       * _.indexOf([1, 1, 2, 2, 3, 3], 2, true);
       * // => 2
       */
      function indexOf(array, value, fromIndex) {
        if (typeof fromIndex == 'number') {
          var length = array ? array.length : 0;
          fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex || 0);
        } else if (fromIndex) {
          var index = sortedIndex(array, value);
          return array[index] === value ? index : -1;
        }
        return baseIndexOf(array, value, fromIndex);
      }
  
      /**
       * Gets all but the last element or last `n` elements of an array. If a
       * callback is provided elements at the end of the array are excluded from
       * the result as long as the callback returns truey. The callback is bound
       * to `thisArg` and invoked with three arguments; (value, index, array).
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @category Arrays
       * @param {Array} array The array to query.
       * @param {Function|Object|number|string} [callback=1] The function called
       *  per element or the number of elements to exclude. If a property name or
       *  object is provided it will be used to create a "_.pluck" or "_.where"
       *  style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {Array} Returns a slice of `array`.
       * @example
       *
       * _.initial([1, 2, 3]);
       * // => [1, 2]
       *
       * _.initial([1, 2, 3], 2);
       * // => [1]
       *
       * _.initial([1, 2, 3], function(num) {
       *   return num > 1;
       * });
       * // => [1]
       *
       * var characters = [
       *   { 'name': 'barney',  'blocked': false, 'employer': 'slate' },
       *   { 'name': 'fred',    'blocked': true,  'employer': 'slate' },
       *   { 'name': 'pebbles', 'blocked': true,  'employer': 'na' }
       * ];
       *
       * // using "_.pluck" callback shorthand
       * _.initial(characters, 'blocked');
       * // => [{ 'name': 'barney',  'blocked': false, 'employer': 'slate' }]
       *
       * // using "_.where" callback shorthand
       * _.pluck(_.initial(characters, { 'employer': 'na' }), 'name');
       * // => ['barney', 'fred']
       */
      function initial(array, callback, thisArg) {
        var n = 0,
            length = array ? array.length : 0;
  
        if (typeof callback != 'number' && callback != null) {
          var index = length;
          callback = lodash.createCallback(callback, thisArg, 3);
          while (index-- && callback(array[index], index, array)) {
            n++;
          }
        } else {
          n = (callback == null || thisArg) ? 1 : callback || n;
        }
        return slice(array, 0, nativeMin(nativeMax(0, length - n), length));
      }
  
      /**
       * Creates an array of unique values present in all provided arrays using
       * strict equality for comparisons, i.e. `===`.
       *
       * @static
       * @memberOf _
       * @category Arrays
       * @param {...Array} [array] The arrays to inspect.
       * @returns {Array} Returns an array of shared values.
       * @example
       *
       * _.intersection([1, 2, 3], [5, 2, 1, 4], [2, 1]);
       * // => [1, 2]
       */
      function intersection() {
        var args = [],
            argsIndex = -1,
            argsLength = arguments.length,
            caches = getArray(),
            indexOf = getIndexOf(),
            trustIndexOf = indexOf === baseIndexOf,
            seen = getArray();
  
        while (++argsIndex < argsLength) {
          var value = arguments[argsIndex];
          if (isArray(value) || isArguments(value)) {
            args.push(value);
            caches.push(trustIndexOf && value.length >= largeArraySize &&
              createCache(argsIndex ? args[argsIndex] : seen));
          }
        }
        var array = args[0],
            index = -1,
            length = array ? array.length : 0,
            result = [];
  
        outer:
        while (++index < length) {
          var cache = caches[0];
          value = array[index];
  
          if ((cache ? cacheIndexOf(cache, value) : indexOf(seen, value)) < 0) {
            argsIndex = argsLength;
            (cache || seen).push(value);
            while (--argsIndex) {
              cache = caches[argsIndex];
              if ((cache ? cacheIndexOf(cache, value) : indexOf(args[argsIndex], value)) < 0) {
                continue outer;
              }
            }
            result.push(value);
          }
        }
        while (argsLength--) {
          cache = caches[argsLength];
          if (cache) {
            releaseObject(cache);
          }
        }
        releaseArray(caches);
        releaseArray(seen);
        return result;
      }
  
      /**
       * Gets the last element or last `n` elements of an array. If a callback is
       * provided elements at the end of the array are returned as long as the
       * callback returns truey. The callback is bound to `thisArg` and invoked
       * with three arguments; (value, index, array).
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @category Arrays
       * @param {Array} array The array to query.
       * @param {Function|Object|number|string} [callback] The function called
       *  per element or the number of elements to return. If a property name or
       *  object is provided it will be used to create a "_.pluck" or "_.where"
       *  style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {*} Returns the last element(s) of `array`.
       * @example
       *
       * _.last([1, 2, 3]);
       * // => 3
       *
       * _.last([1, 2, 3], 2);
       * // => [2, 3]
       *
       * _.last([1, 2, 3], function(num) {
       *   return num > 1;
       * });
       * // => [2, 3]
       *
       * var characters = [
       *   { 'name': 'barney',  'blocked': false, 'employer': 'slate' },
       *   { 'name': 'fred',    'blocked': true,  'employer': 'slate' },
       *   { 'name': 'pebbles', 'blocked': true,  'employer': 'na' }
       * ];
       *
       * // using "_.pluck" callback shorthand
       * _.pluck(_.last(characters, 'blocked'), 'name');
       * // => ['fred', 'pebbles']
       *
       * // using "_.where" callback shorthand
       * _.last(characters, { 'employer': 'na' });
       * // => [{ 'name': 'pebbles', 'blocked': true, 'employer': 'na' }]
       */
      function last(array, callback, thisArg) {
        var n = 0,
            length = array ? array.length : 0;
  
        if (typeof callback != 'number' && callback != null) {
          var index = length;
          callback = lodash.createCallback(callback, thisArg, 3);
          while (index-- && callback(array[index], index, array)) {
            n++;
          }
        } else {
          n = callback;
          if (n == null || thisArg) {
            return array ? array[length - 1] : undefined;
          }
        }
        return slice(array, nativeMax(0, length - n));
      }
  
      /**
       * Gets the index at which the last occurrence of `value` is found using strict
       * equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used
       * as the offset from the end of the collection.
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @category Arrays
       * @param {Array} array The array to search.
       * @param {*} value The value to search for.
       * @param {number} [fromIndex=array.length-1] The index to search from.
       * @returns {number} Returns the index of the matched value or `-1`.
       * @example
       *
       * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2);
       * // => 4
       *
       * _.lastIndexOf([1, 2, 3, 1, 2, 3], 2, 3);
       * // => 1
       */
      function lastIndexOf(array, value, fromIndex) {
        var index = array ? array.length : 0;
        if (typeof fromIndex == 'number') {
          index = (fromIndex < 0 ? nativeMax(0, index + fromIndex) : nativeMin(fromIndex, index - 1)) + 1;
        }
        while (index--) {
          if (array[index] === value) {
            return index;
          }
        }
        return -1;
      }
  
      /**
       * Removes all provided values from the given array using strict equality for
       * comparisons, i.e. `===`.
       *
       * @static
       * @memberOf _
       * @category Arrays
       * @param {Array} array The array to modify.
       * @param {...*} [value] The values to remove.
       * @returns {Array} Returns `array`.
       * @example
       *
       * var array = [1, 2, 3, 1, 2, 3];
       * _.pull(array, 2, 3);
       * console.log(array);
       * // => [1, 1]
       */
      function pull(array) {
        var args = arguments,
            argsIndex = 0,
            argsLength = args.length,
            length = array ? array.length : 0;
  
        while (++argsIndex < argsLength) {
          var index = -1,
              value = args[argsIndex];
          while (++index < length) {
            if (array[index] === value) {
              splice.call(array, index--, 1);
              length--;
            }
          }
        }
        return array;
      }
  
      /**
       * Creates an array of numbers (positive and/or negative) progressing from
       * `start` up to but not including `end`. If `start` is less than `stop` a
       * zero-length range is created unless a negative `step` is specified.
       *
       * @static
       * @memberOf _
       * @category Arrays
       * @param {number} [start=0] The start of the range.
       * @param {number} end The end of the range.
       * @param {number} [step=1] The value to increment or decrement by.
       * @returns {Array} Returns a new range array.
       * @example
       *
       * _.range(4);
       * // => [0, 1, 2, 3]
       *
       * _.range(1, 5);
       * // => [1, 2, 3, 4]
       *
       * _.range(0, 20, 5);
       * // => [0, 5, 10, 15]
       *
       * _.range(0, -4, -1);
       * // => [0, -1, -2, -3]
       *
       * _.range(1, 4, 0);
       * // => [1, 1, 1]
       *
       * _.range(0);
       * // => []
       */
      function range(start, end, step) {
        start = +start || 0;
        step = typeof step == 'number' ? step : (+step || 1);
  
        if (end == null) {
          end = start;
          start = 0;
        }
        // use `Array(length)` so engines like Chakra and V8 avoid slower modes
        // http://youtu.be/XAqIpGU8ZZk#t=17m25s
        var index = -1,
            length = nativeMax(0, ceil((end - start) / (step || 1))),
            result = Array(length);
  
        while (++index < length) {
          result[index] = start;
          start += step;
        }
        return result;
      }
  
      /**
       * Removes all elements from an array that the callback returns truey for
       * and returns an array of removed elements. The callback is bound to `thisArg`
       * and invoked with three arguments; (value, index, array).
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @category Arrays
       * @param {Array} array The array to modify.
       * @param {Function|Object|string} [callback=identity] The function called
       *  per iteration. If a property name or object is provided it will be used
       *  to create a "_.pluck" or "_.where" style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {Array} Returns a new array of removed elements.
       * @example
       *
       * var array = [1, 2, 3, 4, 5, 6];
       * var evens = _.remove(array, function(num) { return num % 2 == 0; });
       *
       * console.log(array);
       * // => [1, 3, 5]
       *
       * console.log(evens);
       * // => [2, 4, 6]
       */
      function remove(array, callback, thisArg) {
        var index = -1,
            length = array ? array.length : 0,
            result = [];
  
        callback = lodash.createCallback(callback, thisArg, 3);
        while (++index < length) {
          var value = array[index];
          if (callback(value, index, array)) {
            result.push(value);
            splice.call(array, index--, 1);
            length--;
          }
        }
        return result;
      }
  
      /**
       * The opposite of `_.initial` this method gets all but the first element or
       * first `n` elements of an array. If a callback function is provided elements
       * at the beginning of the array are excluded from the result as long as the
       * callback returns truey. The callback is bound to `thisArg` and invoked
       * with three arguments; (value, index, array).
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @alias drop, tail
       * @category Arrays
       * @param {Array} array The array to query.
       * @param {Function|Object|number|string} [callback=1] The function called
       *  per element or the number of elements to exclude. If a property name or
       *  object is provided it will be used to create a "_.pluck" or "_.where"
       *  style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {Array} Returns a slice of `array`.
       * @example
       *
       * _.rest([1, 2, 3]);
       * // => [2, 3]
       *
       * _.rest([1, 2, 3], 2);
       * // => [3]
       *
       * _.rest([1, 2, 3], function(num) {
       *   return num < 3;
       * });
       * // => [3]
       *
       * var characters = [
       *   { 'name': 'barney',  'blocked': true,  'employer': 'slate' },
       *   { 'name': 'fred',    'blocked': false,  'employer': 'slate' },
       *   { 'name': 'pebbles', 'blocked': true, 'employer': 'na' }
       * ];
       *
       * // using "_.pluck" callback shorthand
       * _.pluck(_.rest(characters, 'blocked'), 'name');
       * // => ['fred', 'pebbles']
       *
       * // using "_.where" callback shorthand
       * _.rest(characters, { 'employer': 'slate' });
       * // => [{ 'name': 'pebbles', 'blocked': true, 'employer': 'na' }]
       */
      function rest(array, callback, thisArg) {
        if (typeof callback != 'number' && callback != null) {
          var n = 0,
              index = -1,
              length = array ? array.length : 0;
  
          callback = lodash.createCallback(callback, thisArg, 3);
          while (++index < length && callback(array[index], index, array)) {
            n++;
          }
        } else {
          n = (callback == null || thisArg) ? 1 : nativeMax(0, callback);
        }
        return slice(array, n);
      }
  
      /**
       * Uses a binary search to determine the smallest index at which a value
       * should be inserted into a given sorted array in order to maintain the sort
       * order of the array. If a callback is provided it will be executed for
       * `value` and each element of `array` to compute their sort ranking. The
       * callback is bound to `thisArg` and invoked with one argument; (value).
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @category Arrays
       * @param {Array} array The array to inspect.
       * @param {*} value The value to evaluate.
       * @param {Function|Object|string} [callback=identity] The function called
       *  per iteration. If a property name or object is provided it will be used
       *  to create a "_.pluck" or "_.where" style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {number} Returns the index at which `value` should be inserted
       *  into `array`.
       * @example
       *
       * _.sortedIndex([20, 30, 50], 40);
       * // => 2
       *
       * // using "_.pluck" callback shorthand
       * _.sortedIndex([{ 'x': 20 }, { 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x');
       * // => 2
       *
       * var dict = {
       *   'wordToNumber': { 'twenty': 20, 'thirty': 30, 'fourty': 40, 'fifty': 50 }
       * };
       *
       * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
       *   return dict.wordToNumber[word];
       * });
       * // => 2
       *
       * _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
       *   return this.wordToNumber[word];
       * }, dict);
       * // => 2
       */
      function sortedIndex(array, value, callback, thisArg) {
        var low = 0,
            high = array ? array.length : low;
  
        // explicitly reference `identity` for better inlining in Firefox
        callback = callback ? lodash.createCallback(callback, thisArg, 1) : identity;
        value = callback(value);
  
        while (low < high) {
          var mid = (low + high) >>> 1;
          (callback(array[mid]) < value)
            ? low = mid + 1
            : high = mid;
        }
        return low;
      }
  
      /**
       * Creates an array of unique values, in order, of the provided arrays using
       * strict equality for comparisons, i.e. `===`.
       *
       * @static
       * @memberOf _
       * @category Arrays
       * @param {...Array} [array] The arrays to inspect.
       * @returns {Array} Returns an array of combined values.
       * @example
       *
       * _.union([1, 2, 3], [5, 2, 1, 4], [2, 1]);
       * // => [1, 2, 3, 5, 4]
       */
      function union() {
        return baseUniq(baseFlatten(arguments, true, true));
      }
  
      /**
       * Creates a duplicate-value-free version of an array using strict equality
       * for comparisons, i.e. `===`. If the array is sorted, providing
       * `true` for `isSorted` will use a faster algorithm. If a callback is provided
       * each element of `array` is passed through the callback before uniqueness
       * is computed. The callback is bound to `thisArg` and invoked with three
       * arguments; (value, index, array).
       *
       * If a property name is provided for `callback` the created "_.pluck" style
       * callback will return the property value of the given element.
       *
       * If an object is provided for `callback` the created "_.where" style callback
       * will return `true` for elements that have the properties of the given object,
       * else `false`.
       *
       * @static
       * @memberOf _
       * @alias unique
       * @category Arrays
       * @param {Array} array The array to process.
       * @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted.
       * @param {Function|Object|string} [callback=identity] The function called
       *  per iteration. If a property name or object is provided it will be used
       *  to create a "_.pluck" or "_.where" style callback, respectively.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {Array} Returns a duplicate-value-free array.
       * @example
       *
       * _.uniq([1, 2, 1, 3, 1]);
       * // => [1, 2, 3]
       *
       * _.uniq([1, 1, 2, 2, 3], true);
       * // => [1, 2, 3]
       *
       * _.uniq(['A', 'b', 'C', 'a', 'B', 'c'], function(letter) { return letter.toLowerCase(); });
       * // => ['A', 'b', 'C']
       *
       * _.uniq([1, 2.5, 3, 1.5, 2, 3.5], function(num) { return this.floor(num); }, Math);
       * // => [1, 2.5, 3]
       *
       * // using "_.pluck" callback shorthand
       * _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
       * // => [{ 'x': 1 }, { 'x': 2 }]
       */
      function uniq(array, isSorted, callback, thisArg) {
        // juggle arguments
        if (typeof isSorted != 'boolean' && isSorted != null) {
          thisArg = callback;
          callback = (typeof isSorted != 'function' && thisArg && thisArg[isSorted] === array) ? null : isSorted;
          isSorted = false;
        }
        if (callback != null) {
          callback = lodash.createCallback(callback, thisArg, 3);
        }
        return baseUniq(array, isSorted, callback);
      }
  
      /**
       * Creates an array excluding all provided values using strict equality for
       * comparisons, i.e. `===`.
       *
       * @static
       * @memberOf _
       * @category Arrays
       * @param {Array} array The array to filter.
       * @param {...*} [value] The values to exclude.
       * @returns {Array} Returns a new array of filtered values.
       * @example
       *
       * _.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
       * // => [2, 3, 4]
       */
      function without(array) {
        return baseDifference(array, slice(arguments, 1));
      }
  
      /**
       * Creates an array that is the symmetric difference of the provided arrays.
       * See http://en.wikipedia.org/wiki/Symmetric_difference.
       *
       * @static
       * @memberOf _
       * @category Arrays
       * @param {...Array} [array] The arrays to inspect.
       * @returns {Array} Returns an array of values.
       * @example
       *
       * _.xor([1, 2, 3], [5, 2, 1, 4]);
       * // => [3, 5, 4]
       *
       * _.xor([1, 2, 5], [2, 3, 5], [3, 4, 5]);
       * // => [1, 4, 5]
       */
      function xor() {
        var index = -1,
            length = arguments.length;
  
        while (++index < length) {
          var array = arguments[index];
          if (isArray(array) || isArguments(array)) {
            var result = result
              ? baseUniq(baseDifference(result, array).concat(baseDifference(array, result)))
              : array;
          }
        }
        return result || [];
      }
  
      /**
       * Creates an array of grouped elements, the first of which contains the first
       * elements of the given arrays, the second of which contains the second
       * elements of the given arrays, and so on.
       *
       * @static
       * @memberOf _
       * @alias unzip
       * @category Arrays
       * @param {...Array} [array] Arrays to process.
       * @returns {Array} Returns a new array of grouped elements.
       * @example
       *
       * _.zip(['fred', 'barney'], [30, 40], [true, false]);
       * // => [['fred', 30, true], ['barney', 40, false]]
       */
      function zip() {
        var array = arguments.length > 1 ? arguments : arguments[0],
            index = -1,
            length = array ? max(pluck(array, 'length')) : 0,
            result = Array(length < 0 ? 0 : length);
  
        while (++index < length) {
          result[index] = pluck(array, index);
        }
        return result;
      }
  
      /**
       * Creates an object composed from arrays of `keys` and `values`. Provide
       * either a single two dimensional array, i.e. `[[key1, value1], [key2, value2]]`
       * or two arrays, one of `keys` and one of corresponding `values`.
       *
       * @static
       * @memberOf _
       * @alias object
       * @category Arrays
       * @param {Array} keys The array of keys.
       * @param {Array} [values=[]] The array of values.
       * @returns {Object} Returns an object composed of the given keys and
       *  corresponding values.
       * @example
       *
       * _.zipObject(['fred', 'barney'], [30, 40]);
       * // => { 'fred': 30, 'barney': 40 }
       */
      function zipObject(keys, values) {
        var index = -1,
            length = keys ? keys.length : 0,
            result = {};
  
        if (!values && length && !isArray(keys[0])) {
          values = [];
        }
        while (++index < length) {
          var key = keys[index];
          if (values) {
            result[key] = values[index];
          } else if (key) {
            result[key[0]] = key[1];
          }
        }
        return result;
      }
  
      /*--------------------------------------------------------------------------*/
  
      /**
       * Creates a function that executes `func`, with  the `this` binding and
       * arguments of the created function, only after being called `n` times.
       *
       * @static
       * @memberOf _
       * @category Functions
       * @param {number} n The number of times the function must be called before
       *  `func` is executed.
       * @param {Function} func The function to restrict.
       * @returns {Function} Returns the new restricted function.
       * @example
       *
       * var saves = ['profile', 'settings'];
       *
       * var done = _.after(saves.length, function() {
       *   console.log('Done saving!');
       * });
       *
       * _.forEach(saves, function(type) {
       *   asyncSave({ 'type': type, 'complete': done });
       * });
       * // => logs 'Done saving!', after all saves have completed
       */
      function after(n, func) {
        if (!isFunction(func)) {
          throw new TypeError;
        }
        return function() {
          if (--n < 1) {
            return func.apply(this, arguments);
          }
        };
      }
  
      /**
       * Creates a function that, when called, invokes `func` with the `this`
       * binding of `thisArg` and prepends any additional `bind` arguments to those
       * provided to the bound function.
       *
       * @static
       * @memberOf _
       * @category Functions
       * @param {Function} func The function to bind.
       * @param {*} [thisArg] The `this` binding of `func`.
       * @param {...*} [arg] Arguments to be partially applied.
       * @returns {Function} Returns the new bound function.
       * @example
       *
       * var func = function(greeting) {
       *   return greeting + ' ' + this.name;
       * };
       *
       * func = _.bind(func, { 'name': 'fred' }, 'hi');
       * func();
       * // => 'hi fred'
       */
      function bind(func, thisArg) {
        return arguments.length > 2
          ? createWrapper(func, 17, slice(arguments, 2), null, thisArg)
          : createWrapper(func, 1, null, null, thisArg);
      }
  
      /**
       * Binds methods of an object to the object itself, overwriting the existing
       * method. Method names may be specified as individual arguments or as arrays
       * of method names. If no method names are provided all the function properties
       * of `object` will be bound.
       *
       * @static
       * @memberOf _
       * @category Functions
       * @param {Object} object The object to bind and assign the bound methods to.
       * @param {...string} [methodName] The object method names to
       *  bind, specified as individual method names or arrays of method names.
       * @returns {Object} Returns `object`.
       * @example
       *
       * var view = {
       *   'label': 'docs',
       *   'onClick': function() { console.log('clicked ' + this.label); }
       * };
       *
       * _.bindAll(view);
       * jQuery('#docs').on('click', view.onClick);
       * // => logs 'clicked docs', when the button is clicked
       */
      function bindAll(object) {
        var funcs = arguments.length > 1 ? baseFlatten(arguments, true, false, 1) : functions(object),
            index = -1,
            length = funcs.length;
  
        while (++index < length) {
          var key = funcs[index];
          object[key] = createWrapper(object[key], 1, null, null, object);
        }
        return object;
      }
  
      /**
       * Creates a function that, when called, invokes the method at `object[key]`
       * and prepends any additional `bindKey` arguments to those provided to the bound
       * function. This method differs from `_.bind` by allowing bound functions to
       * reference methods that will be redefined or don't yet exist.
       * See http://michaux.ca/articles/lazy-function-definition-pattern.
       *
       * @static
       * @memberOf _
       * @category Functions
       * @param {Object} object The object the method belongs to.
       * @param {string} key The key of the method.
       * @param {...*} [arg] Arguments to be partially applied.
       * @returns {Function} Returns the new bound function.
       * @example
       *
       * var object = {
       *   'name': 'fred',
       *   'greet': function(greeting) {
       *     return greeting + ' ' + this.name;
       *   }
       * };
       *
       * var func = _.bindKey(object, 'greet', 'hi');
       * func();
       * // => 'hi fred'
       *
       * object.greet = function(greeting) {
       *   return greeting + 'ya ' + this.name + '!';
       * };
       *
       * func();
       * // => 'hiya fred!'
       */
      function bindKey(object, key) {
        return arguments.length > 2
          ? createWrapper(key, 19, slice(arguments, 2), null, object)
          : createWrapper(key, 3, null, null, object);
      }
  
      /**
       * Creates a function that is the composition of the provided functions,
       * where each function consumes the return value of the function that follows.
       * For example, composing the functions `f()`, `g()`, and `h()` produces `f(g(h()))`.
       * Each function is executed with the `this` binding of the composed function.
       *
       * @static
       * @memberOf _
       * @category Functions
       * @param {...Function} [func] Functions to compose.
       * @returns {Function} Returns the new composed function.
       * @example
       *
       * var realNameMap = {
       *   'pebbles': 'penelope'
       * };
       *
       * var format = function(name) {
       *   name = realNameMap[name.toLowerCase()] || name;
       *   return name.charAt(0).toUpperCase() + name.slice(1).toLowerCase();
       * };
       *
       * var greet = function(formatted) {
       *   return 'Hiya ' + formatted + '!';
       * };
       *
       * var welcome = _.compose(greet, format);
       * welcome('pebbles');
       * // => 'Hiya Penelope!'
       */
      function compose() {
        var funcs = arguments,
            length = funcs.length;
  
        while (length--) {
          if (!isFunction(funcs[length])) {
            throw new TypeError;
          }
        }
        return function() {
          var args = arguments,
              length = funcs.length;
  
          while (length--) {
            args = [funcs[length].apply(this, args)];
          }
          return args[0];
        };
      }
  
      /**
       * Creates a function which accepts one or more arguments of `func` that when
       * invoked either executes `func` returning its result, if all `func` arguments
       * have been provided, or returns a function that accepts one or more of the
       * remaining `func` arguments, and so on. The arity of `func` can be specified
       * if `func.length` is not sufficient.
       *
       * @static
       * @memberOf _
       * @category Functions
       * @param {Function} func The function to curry.
       * @param {number} [arity=func.length] The arity of `func`.
       * @returns {Function} Returns the new curried function.
       * @example
       *
       * var curried = _.curry(function(a, b, c) {
       *   console.log(a + b + c);
       * });
       *
       * curried(1)(2)(3);
       * // => 6
       *
       * curried(1, 2)(3);
       * // => 6
       *
       * curried(1, 2, 3);
       * // => 6
       */
      function curry(func, arity) {
        arity = typeof arity == 'number' ? arity : (+arity || func.length);
        return createWrapper(func, 4, null, null, null, arity);
      }
  
      /**
       * Creates a function that will delay the execution of `func` until after
       * `wait` milliseconds have elapsed since the last time it was invoked.
       * Provide an options object to indicate that `func` should be invoked on
       * the leading and/or trailing edge of the `wait` timeout. Subsequent calls
       * to the debounced function will return the result of the last `func` call.
       *
       * Note: If `leading` and `trailing` options are `true` `func` will be called
       * on the trailing edge of the timeout only if the the debounced function is
       * invoked more than once during the `wait` timeout.
       *
       * @static
       * @memberOf _
       * @category Functions
       * @param {Function} func The function to debounce.
       * @param {number} wait The number of milliseconds to delay.
       * @param {Object} [options] The options object.
       * @param {boolean} [options.leading=false] Specify execution on the leading edge of the timeout.
       * @param {number} [options.maxWait] The maximum time `func` is allowed to be delayed before it's called.
       * @param {boolean} [options.trailing=true] Specify execution on the trailing edge of the timeout.
       * @returns {Function} Returns the new debounced function.
       * @example
       *
       * // avoid costly calculations while the window size is in flux
       * var lazyLayout = _.debounce(calculateLayout, 150);
       * jQuery(window).on('resize', lazyLayout);
       *
       * // execute `sendMail` when the click event is fired, debouncing subsequent calls
       * jQuery('#postbox').on('click', _.debounce(sendMail, 300, {
       *   'leading': true,
       *   'trailing': false
       * });
       *
       * // ensure `batchLog` is executed once after 1 second of debounced calls
       * var source = new EventSource('/stream');
       * source.addEventListener('message', _.debounce(batchLog, 250, {
       *   'maxWait': 1000
       * }, false);
       */
      function debounce(func, wait, options) {
        var args,
            maxTimeoutId,
            result,
            stamp,
            thisArg,
            timeoutId,
            trailingCall,
            lastCalled = 0,
            maxWait = false,
            trailing = true;
  
        if (!isFunction(func)) {
          throw new TypeError;
        }
        wait = nativeMax(0, wait) || 0;
        if (options === true) {
          var leading = true;
          trailing = false;
        } else if (isObject(options)) {
          leading = options.leading;
          maxWait = 'maxWait' in options && (nativeMax(wait, options.maxWait) || 0);
          trailing = 'trailing' in options ? options.trailing : trailing;
        }
        var delayed = function() {
          var remaining = wait - (now() - stamp);
          if (remaining <= 0) {
            if (maxTimeoutId) {
              clearTimeout(maxTimeoutId);
            }
            var isCalled = trailingCall;
            maxTimeoutId = timeoutId = trailingCall = undefined;
            if (isCalled) {
              lastCalled = now();
              result = func.apply(thisArg, args);
              if (!timeoutId && !maxTimeoutId) {
                args = thisArg = null;
              }
            }
          } else {
            timeoutId = setTimeout(delayed, remaining);
          }
        };
  
        var maxDelayed = function() {
          if (timeoutId) {
            clearTimeout(timeoutId);
          }
          maxTimeoutId = timeoutId = trailingCall = undefined;
          if (trailing || (maxWait !== wait)) {
            lastCalled = now();
            result = func.apply(thisArg, args);
            if (!timeoutId && !maxTimeoutId) {
              args = thisArg = null;
            }
          }
        };
  
        return function() {
          args = arguments;
          stamp = now();
          thisArg = this;
          trailingCall = trailing && (timeoutId || !leading);
  
          if (maxWait === false) {
            var leadingCall = leading && !timeoutId;
          } else {
            if (!maxTimeoutId && !leading) {
              lastCalled = stamp;
            }
            var remaining = maxWait - (stamp - lastCalled),
                isCalled = remaining <= 0;
  
            if (isCalled) {
              if (maxTimeoutId) {
                maxTimeoutId = clearTimeout(maxTimeoutId);
              }
              lastCalled = stamp;
              result = func.apply(thisArg, args);
            }
            else if (!maxTimeoutId) {
              maxTimeoutId = setTimeout(maxDelayed, remaining);
            }
          }
          if (isCalled && timeoutId) {
            timeoutId = clearTimeout(timeoutId);
          }
          else if (!timeoutId && wait !== maxWait) {
            timeoutId = setTimeout(delayed, wait);
          }
          if (leadingCall) {
            isCalled = true;
            result = func.apply(thisArg, args);
          }
          if (isCalled && !timeoutId && !maxTimeoutId) {
            args = thisArg = null;
          }
          return result;
        };
      }
  
      /**
       * Defers executing the `func` function until the current call stack has cleared.
       * Additional arguments will be provided to `func` when it is invoked.
       *
       * @static
       * @memberOf _
       * @category Functions
       * @param {Function} func The function to defer.
       * @param {...*} [arg] Arguments to invoke the function with.
       * @returns {number} Returns the timer id.
       * @example
       *
       * _.defer(function(text) { console.log(text); }, 'deferred');
       * // logs 'deferred' after one or more milliseconds
       */
      function defer(func) {
        if (!isFunction(func)) {
          throw new TypeError;
        }
        var args = slice(arguments, 1);
        return setTimeout(function() { func.apply(undefined, args); }, 1);
      }
  
      /**
       * Executes the `func` function after `wait` milliseconds. Additional arguments
       * will be provided to `func` when it is invoked.
       *
       * @static
       * @memberOf _
       * @category Functions
       * @param {Function} func The function to delay.
       * @param {number} wait The number of milliseconds to delay execution.
       * @param {...*} [arg] Arguments to invoke the function with.
       * @returns {number} Returns the timer id.
       * @example
       *
       * _.delay(function(text) { console.log(text); }, 1000, 'later');
       * // => logs 'later' after one second
       */
      function delay(func, wait) {
        if (!isFunction(func)) {
          throw new TypeError;
        }
        var args = slice(arguments, 2);
        return setTimeout(function() { func.apply(undefined, args); }, wait);
      }
  
      /**
       * Creates a function that memoizes the result of `func`. If `resolver` is
       * provided it will be used to determine the cache key for storing the result
       * based on the arguments provided to the memoized function. By default, the
       * first argument provided to the memoized function is used as the cache key.
       * The `func` is executed with the `this` binding of the memoized function.
       * The result cache is exposed as the `cache` property on the memoized function.
       *
       * @static
       * @memberOf _
       * @category Functions
       * @param {Function} func The function to have its output memoized.
       * @param {Function} [resolver] A function used to resolve the cache key.
       * @returns {Function} Returns the new memoizing function.
       * @example
       *
       * var fibonacci = _.memoize(function(n) {
       *   return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
       * });
       *
       * fibonacci(9)
       * // => 34
       *
       * var data = {
       *   'fred': { 'name': 'fred', 'age': 40 },
       *   'pebbles': { 'name': 'pebbles', 'age': 1 }
       * };
       *
       * // modifying the result cache
       * var get = _.memoize(function(name) { return data[name]; }, _.identity);
       * get('pebbles');
       * // => { 'name': 'pebbles', 'age': 1 }
       *
       * get.cache.pebbles.name = 'penelope';
       * get('pebbles');
       * // => { 'name': 'penelope', 'age': 1 }
       */
      function memoize(func, resolver) {
        if (!isFunction(func)) {
          throw new TypeError;
        }
        var memoized = function() {
          var cache = memoized.cache,
              key = resolver ? resolver.apply(this, arguments) : keyPrefix + arguments[0];
  
          return hasOwnProperty.call(cache, key)
            ? cache[key]
            : (cache[key] = func.apply(this, arguments));
        }
        memoized.cache = {};
        return memoized;
      }
  
      /**
       * Creates a function that is restricted to execute `func` once. Repeat calls to
       * the function will return the value of the first call. The `func` is executed
       * with the `this` binding of the created function.
       *
       * @static
       * @memberOf _
       * @category Functions
       * @param {Function} func The function to restrict.
       * @returns {Function} Returns the new restricted function.
       * @example
       *
       * var initialize = _.once(createApplication);
       * initialize();
       * initialize();
       * // `initialize` executes `createApplication` once
       */
      function once(func) {
        var ran,
            result;
  
        if (!isFunction(func)) {
          throw new TypeError;
        }
        return function() {
          if (ran) {
            return result;
          }
          ran = true;
          result = func.apply(this, arguments);
  
          // clear the `func` variable so the function may be garbage collected
          func = null;
          return result;
        };
      }
  
      /**
       * Creates a function that, when called, invokes `func` with any additional
       * `partial` arguments prepended to those provided to the new function. This
       * method is similar to `_.bind` except it does **not** alter the `this` binding.
       *
       * @static
       * @memberOf _
       * @category Functions
       * @param {Function} func The function to partially apply arguments to.
       * @param {...*} [arg] Arguments to be partially applied.
       * @returns {Function} Returns the new partially applied function.
       * @example
       *
       * var greet = function(greeting, name) { return greeting + ' ' + name; };
       * var hi = _.partial(greet, 'hi');
       * hi('fred');
       * // => 'hi fred'
       */
      function partial(func) {
        return createWrapper(func, 16, slice(arguments, 1));
      }
  
      /**
       * This method is like `_.partial` except that `partial` arguments are
       * appended to those provided to the new function.
       *
       * @static
       * @memberOf _
       * @category Functions
       * @param {Function} func The function to partially apply arguments to.
       * @param {...*} [arg] Arguments to be partially applied.
       * @returns {Function} Returns the new partially applied function.
       * @example
       *
       * var defaultsDeep = _.partialRight(_.merge, _.defaults);
       *
       * var options = {
       *   'variable': 'data',
       *   'imports': { 'jq': $ }
       * };
       *
       * defaultsDeep(options, _.templateSettings);
       *
       * options.variable
       * // => 'data'
       *
       * options.imports
       * // => { '_': _, 'jq': $ }
       */
      function partialRight(func) {
        return createWrapper(func, 32, null, slice(arguments, 1));
      }
  
      /**
       * Creates a function that, when executed, will only call the `func` function
       * at most once per every `wait` milliseconds. Provide an options object to
       * indicate that `func` should be invoked on the leading and/or trailing edge
       * of the `wait` timeout. Subsequent calls to the throttled function will
       * return the result of the last `func` call.
       *
       * Note: If `leading` and `trailing` options are `true` `func` will be called
       * on the trailing edge of the timeout only if the the throttled function is
       * invoked more than once during the `wait` timeout.
       *
       * @static
       * @memberOf _
       * @category Functions
       * @param {Function} func The function to throttle.
       * @param {number} wait The number of milliseconds to throttle executions to.
       * @param {Object} [options] The options object.
       * @param {boolean} [options.leading=true] Specify execution on the leading edge of the timeout.
       * @param {boolean} [options.trailing=true] Specify execution on the trailing edge of the timeout.
       * @returns {Function} Returns the new throttled function.
       * @example
       *
       * // avoid excessively updating the position while scrolling
       * var throttled = _.throttle(updatePosition, 100);
       * jQuery(window).on('scroll', throttled);
       *
       * // execute `renewToken` when the click event is fired, but not more than once every 5 minutes
       * jQuery('.interactive').on('click', _.throttle(renewToken, 300000, {
       *   'trailing': false
       * }));
       */
      function throttle(func, wait, options) {
        var leading = true,
            trailing = true;
  
        if (!isFunction(func)) {
          throw new TypeError;
        }
        if (options === false) {
          leading = false;
        } else if (isObject(options)) {
          leading = 'leading' in options ? options.leading : leading;
          trailing = 'trailing' in options ? options.trailing : trailing;
        }
        debounceOptions.leading = leading;
        debounceOptions.maxWait = wait;
        debounceOptions.trailing = trailing;
  
        return debounce(func, wait, debounceOptions);
      }
  
      /**
       * Creates a function that provides `value` to the wrapper function as its
       * first argument. Additional arguments provided to the function are appended
       * to those provided to the wrapper function. The wrapper is executed with
       * the `this` binding of the created function.
       *
       * @static
       * @memberOf _
       * @category Functions
       * @param {*} value The value to wrap.
       * @param {Function} wrapper The wrapper function.
       * @returns {Function} Returns the new function.
       * @example
       *
       * var p = _.wrap(_.escape, function(func, text) {
       *   return '<p>' + func(text) + '</p>';
       * });
       *
       * p('Fred, Wilma, & Pebbles');
       * // => '<p>Fred, Wilma, &amp; Pebbles</p>'
       */
      function wrap(value, wrapper) {
        return createWrapper(wrapper, 16, [value]);
      }
  
      /*--------------------------------------------------------------------------*/
  
      /**
       * Creates a function that returns `value`.
       *
       * @static
       * @memberOf _
       * @category Utilities
       * @param {*} value The value to return from the new function.
       * @returns {Function} Returns the new function.
       * @example
       *
       * var object = { 'name': 'fred' };
       * var getter = _.constant(object);
       * getter() === object;
       * // => true
       */
      function constant(value) {
        return function() {
          return value;
        };
      }
  
      /**
       * Produces a callback bound to an optional `thisArg`. If `func` is a property
       * name the created callback will return the property value for a given element.
       * If `func` is an object the created callback will return `true` for elements
       * that contain the equivalent object properties, otherwise it will return `false`.
       *
       * @static
       * @memberOf _
       * @category Utilities
       * @param {*} [func=identity] The value to convert to a callback.
       * @param {*} [thisArg] The `this` binding of the created callback.
       * @param {number} [argCount] The number of arguments the callback accepts.
       * @returns {Function} Returns a callback function.
       * @example
       *
       * var characters = [
       *   { 'name': 'barney', 'age': 36 },
       *   { 'name': 'fred',   'age': 40 }
       * ];
       *
       * // wrap to create custom callback shorthands
       * _.createCallback = _.wrap(_.createCallback, function(func, callback, thisArg) {
       *   var match = /^(.+?)__([gl]t)(.+)$/.exec(callback);
       *   return !match ? func(callback, thisArg) : function(object) {
       *     return match[2] == 'gt' ? object[match[1]] > match[3] : object[match[1]] < match[3];
       *   };
       * });
       *
       * _.filter(characters, 'age__gt38');
       * // => [{ 'name': 'fred', 'age': 40 }]
       */
      function createCallback(func, thisArg, argCount) {
        var type = typeof func;
        if (func == null || type == 'function') {
          return baseCreateCallback(func, thisArg, argCount);
        }
        // handle "_.pluck" style callback shorthands
        if (type != 'object') {
          return property(func);
        }
        var props = keys(func),
            key = props[0],
            a = func[key];
  
        // handle "_.where" style callback shorthands
        if (props.length == 1 && a === a && !isObject(a)) {
          // fast path the common case of providing an object with a single
          // property containing a primitive value
          return function(object) {
            var b = object[key];
            return a === b && (a !== 0 || (1 / a == 1 / b));
          };
        }
        return function(object) {
          var length = props.length,
              result = false;
  
          while (length--) {
            if (!(result = baseIsEqual(object[props[length]], func[props[length]], null, true))) {
              break;
            }
          }
          return result;
        };
      }
  
      /**
       * Converts the characters `&`, `<`, `>`, `"`, and `'` in `string` to their
       * corresponding HTML entities.
       *
       * @static
       * @memberOf _
       * @category Utilities
       * @param {string} string The string to escape.
       * @returns {string} Returns the escaped string.
       * @example
       *
       * _.escape('Fred, Wilma, & Pebbles');
       * // => 'Fred, Wilma, &amp; Pebbles'
       */
      function escape(string) {
        return string == null ? '' : String(string).replace(reUnescapedHtml, escapeHtmlChar);
      }
  
      /**
       * This method returns the first argument provided to it.
       *
       * @static
       * @memberOf _
       * @category Utilities
       * @param {*} value Any value.
       * @returns {*} Returns `value`.
       * @example
       *
       * var object = { 'name': 'fred' };
       * _.identity(object) === object;
       * // => true
       */
      function identity(value) {
        return value;
      }
  
      /**
       * Adds function properties of a source object to the destination object.
       * If `object` is a function methods will be added to its prototype as well.
       *
       * @static
       * @memberOf _
       * @category Utilities
       * @param {Function|Object} [object=lodash] object The destination object.
       * @param {Object} source The object of functions to add.
       * @param {Object} [options] The options object.
       * @param {boolean} [options.chain=true] Specify whether the functions added are chainable.
       * @example
       *
       * function capitalize(string) {
       *   return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase();
       * }
       *
       * _.mixin({ 'capitalize': capitalize });
       * _.capitalize('fred');
       * // => 'Fred'
       *
       * _('fred').capitalize().value();
       * // => 'Fred'
       *
       * _.mixin({ 'capitalize': capitalize }, { 'chain': false });
       * _('fred').capitalize();
       * // => 'Fred'
       */
      function mixin(object, source, options) {
        var chain = true,
            methodNames = source && functions(source);
  
        if (!source || (!options && !methodNames.length)) {
          if (options == null) {
            options = source;
          }
          ctor = lodashWrapper;
          source = object;
          object = lodash;
          methodNames = functions(source);
        }
        if (options === false) {
          chain = false;
        } else if (isObject(options) && 'chain' in options) {
          chain = options.chain;
        }
        var ctor = object,
            isFunc = isFunction(ctor);
  
        forEach(methodNames, function(methodName) {
          var func = object[methodName] = source[methodName];
          if (isFunc) {
            ctor.prototype[methodName] = function() {
              var chainAll = this.__chain__,
                  value = this.__wrapped__,
                  args = [value];
  
              push.apply(args, arguments);
              var result = func.apply(object, args);
              if (chain || chainAll) {
                if (value === result && isObject(result)) {
                  return this;
                }
                result = new ctor(result);
                result.__chain__ = chainAll;
              }
              return result;
            };
          }
        });
      }
  
      /**
       * Reverts the '_' variable to its previous value and returns a reference to
       * the `lodash` function.
       *
       * @static
       * @memberOf _
       * @category Utilities
       * @returns {Function} Returns the `lodash` function.
       * @example
       *
       * var lodash = _.noConflict();
       */
      function noConflict() {
        context._ = oldDash;
        return this;
      }
  
      /**
       * A no-operation function.
       *
       * @static
       * @memberOf _
       * @category Utilities
       * @example
       *
       * var object = { 'name': 'fred' };
       * _.noop(object) === undefined;
       * // => true
       */
      function noop() {
        // no operation performed
      }
  
      /**
       * Gets the number of milliseconds that have elapsed since the Unix epoch
       * (1 January 1970 00:00:00 UTC).
       *
       * @static
       * @memberOf _
       * @category Utilities
       * @example
       *
       * var stamp = _.now();
       * _.defer(function() { console.log(_.now() - stamp); });
       * // => logs the number of milliseconds it took for the deferred function to be called
       */
      var now = isNative(now = Date.now) && now || function() {
        return new Date().getTime();
      };
  
      /**
       * Converts the given value into an integer of the specified radix.
       * If `radix` is `undefined` or `0` a `radix` of `10` is used unless the
       * `value` is a hexadecimal, in which case a `radix` of `16` is used.
       *
       * Note: This method avoids differences in native ES3 and ES5 `parseInt`
       * implementations. See http://es5.github.io/#E.
       *
       * @static
       * @memberOf _
       * @category Utilities
       * @param {string} value The value to parse.
       * @param {number} [radix] The radix used to interpret the value to parse.
       * @returns {number} Returns the new integer value.
       * @example
       *
       * _.parseInt('08');
       * // => 8
       */
      var parseInt = nativeParseInt(whitespace + '08') == 8 ? nativeParseInt : function(value, radix) {
        // Firefox < 21 and Opera < 15 follow the ES3 specified implementation of `parseInt`
        return nativeParseInt(isString(value) ? value.replace(reLeadingSpacesAndZeros, '') : value, radix || 0);
      };
  
      /**
       * Creates a "_.pluck" style function, which returns the `key` value of a
       * given object.
       *
       * @static
       * @memberOf _
       * @category Utilities
       * @param {string} key The name of the property to retrieve.
       * @returns {Function} Returns the new function.
       * @example
       *
       * var characters = [
       *   { 'name': 'fred',   'age': 40 },
       *   { 'name': 'barney', 'age': 36 }
       * ];
       *
       * var getName = _.property('name');
       *
       * _.map(characters, getName);
       * // => ['barney', 'fred']
       *
       * _.sortBy(characters, getName);
       * // => [{ 'name': 'barney', 'age': 36 }, { 'name': 'fred',   'age': 40 }]
       */
      function property(key) {
        return function(object) {
          return object[key];
        };
      }
  
      /**
       * Produces a random number between `min` and `max` (inclusive). If only one
       * argument is provided a number between `0` and the given number will be
       * returned. If `floating` is truey or either `min` or `max` are floats a
       * floating-point number will be returned instead of an integer.
       *
       * @static
       * @memberOf _
       * @category Utilities
       * @param {number} [min=0] The minimum possible value.
       * @param {number} [max=1] The maximum possible value.
       * @param {boolean} [floating=false] Specify returning a floating-point number.
       * @returns {number} Returns a random number.
       * @example
       *
       * _.random(0, 5);
       * // => an integer between 0 and 5
       *
       * _.random(5);
       * // => also an integer between 0 and 5
       *
       * _.random(5, true);
       * // => a floating-point number between 0 and 5
       *
       * _.random(1.2, 5.2);
       * // => a floating-point number between 1.2 and 5.2
       */
      function random(min, max, floating) {
        var noMin = min == null,
            noMax = max == null;
  
        if (floating == null) {
          if (typeof min == 'boolean' && noMax) {
            floating = min;
            min = 1;
          }
          else if (!noMax && typeof max == 'boolean') {
            floating = max;
            noMax = true;
          }
        }
        if (noMin && noMax) {
          max = 1;
        }
        min = +min || 0;
        if (noMax) {
          max = min;
          min = 0;
        } else {
          max = +max || 0;
        }
        if (floating || min % 1 || max % 1) {
          var rand = nativeRandom();
          return nativeMin(min + (rand * (max - min + parseFloat('1e-' + ((rand +'').length - 1)))), max);
        }
        return baseRandom(min, max);
      }
  
      /**
       * Resolves the value of property `key` on `object`. If `key` is a function
       * it will be invoked with the `this` binding of `object` and its result returned,
       * else the property value is returned. If `object` is falsey then `undefined`
       * is returned.
       *
       * @static
       * @memberOf _
       * @category Utilities
       * @param {Object} object The object to inspect.
       * @param {string} key The name of the property to resolve.
       * @returns {*} Returns the resolved value.
       * @example
       *
       * var object = {
       *   'cheese': 'crumpets',
       *   'stuff': function() {
       *     return 'nonsense';
       *   }
       * };
       *
       * _.result(object, 'cheese');
       * // => 'crumpets'
       *
       * _.result(object, 'stuff');
       * // => 'nonsense'
       */
      function result(object, key) {
        if (object) {
          var value = object[key];
          return isFunction(value) ? object[key]() : value;
        }
      }
  
      /**
       * A micro-templating method that handles arbitrary delimiters, preserves
       * whitespace, and correctly escapes quotes within interpolated code.
       *
       * Note: In the development build, `_.template` utilizes sourceURLs for easier
       * debugging. See http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl
       *
       * For more information on precompiling templates see:
       * http://lodash.com/custom-builds
       *
       * For more information on Chrome extension sandboxes see:
       * http://developer.chrome.com/stable/extensions/sandboxingEval.html
       *
       * @static
       * @memberOf _
       * @category Utilities
       * @param {string} text The template text.
       * @param {Object} data The data object used to populate the text.
       * @param {Object} [options] The options object.
       * @param {RegExp} [options.escape] The "escape" delimiter.
       * @param {RegExp} [options.evaluate] The "evaluate" delimiter.
       * @param {Object} [options.imports] An object to import into the template as local variables.
       * @param {RegExp} [options.interpolate] The "interpolate" delimiter.
       * @param {string} [sourceURL] The sourceURL of the template's compiled source.
       * @param {string} [variable] The data object variable name.
       * @returns {Function|string} Returns a compiled function when no `data` object
       *  is given, else it returns the interpolated text.
       * @example
       *
       * // using the "interpolate" delimiter to create a compiled template
       * var compiled = _.template('hello <%= name %>');
       * compiled({ 'name': 'fred' });
       * // => 'hello fred'
       *
       * // using the "escape" delimiter to escape HTML in data property values
       * _.template('<b><%- value %></b>', { 'value': '<script>' });
       * // => '<b>&lt;script&gt;</b>'
       *
       * // using the "evaluate" delimiter to generate HTML
       * var list = '<% _.forEach(people, function(name) { %><li><%- name %></li><% }); %>';
       * _.template(list, { 'people': ['fred', 'barney'] });
       * // => '<li>fred</li><li>barney</li>'
       *
       * // using the ES6 delimiter as an alternative to the default "interpolate" delimiter
       * _.template('hello ${ name }', { 'name': 'pebbles' });
       * // => 'hello pebbles'
       *
       * // using the internal `print` function in "evaluate" delimiters
       * _.template('<% print("hello " + name); %>!', { 'name': 'barney' });
       * // => 'hello barney!'
       *
       * // using a custom template delimiters
       * _.templateSettings = {
       *   'interpolate': /{{([\s\S]+?)}}/g
       * };
       *
       * _.template('hello {{ name }}!', { 'name': 'mustache' });
       * // => 'hello mustache!'
       *
       * // using the `imports` option to import jQuery
       * var list = '<% jq.each(people, function(name) { %><li><%- name %></li><% }); %>';
       * _.template(list, { 'people': ['fred', 'barney'] }, { 'imports': { 'jq': jQuery } });
       * // => '<li>fred</li><li>barney</li>'
       *
       * // using the `sourceURL` option to specify a custom sourceURL for the template
       * var compiled = _.template('hello <%= name %>', null, { 'sourceURL': '/basic/greeting.jst' });
       * compiled(data);
       * // => find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector
       *
       * // using the `variable` option to ensure a with-statement isn't used in the compiled template
       * var compiled = _.template('hi <%= data.name %>!', null, { 'variable': 'data' });
       * compiled.source;
       * // => function(data) {
       *   var __t, __p = '', __e = _.escape;
       *   __p += 'hi ' + ((__t = ( data.name )) == null ? '' : __t) + '!';
       *   return __p;
       * }
       *
       * // using the `source` property to inline compiled templates for meaningful
       * // line numbers in error messages and a stack trace
       * fs.writeFileSync(path.join(cwd, 'jst.js'), '\
       *   var JST = {\
       *     "main": ' + _.template(mainText).source + '\
       *   };\
       * ');
       */
      function template(text, data, options) {
        // based on John Resig's `tmpl` implementation
        // http://ejohn.org/blog/javascript-micro-templating/
        // and Laura Doktorova's doT.js
        // https://github.com/olado/doT
        var settings = lodash.templateSettings;
        text = String(text || '');
  
        // avoid missing dependencies when `iteratorTemplate` is not defined
        options = defaults({}, options, settings);
  
        var imports = defaults({}, options.imports, settings.imports),
            importsKeys = keys(imports),
            importsValues = values(imports);
  
        var isEvaluating,
            index = 0,
            interpolate = options.interpolate || reNoMatch,
            source = "__p += '";
  
        // compile the regexp to match each delimiter
        var reDelimiters = RegExp(
          (options.escape || reNoMatch).source + '|' +
          interpolate.source + '|' +
          (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' +
          (options.evaluate || reNoMatch).source + '|$'
        , 'g');
  
        text.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
          interpolateValue || (interpolateValue = esTemplateValue);
  
          // escape characters that cannot be included in string literals
          source += text.slice(index, offset).replace(reUnescapedString, escapeStringChar);
  
          // replace delimiters with snippets
          if (escapeValue) {
            source += "' +\n__e(" + escapeValue + ") +\n'";
          }
          if (evaluateValue) {
            isEvaluating = true;
            source += "';\n" + evaluateValue + ";\n__p += '";
          }
          if (interpolateValue) {
            source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
          }
          index = offset + match.length;
  
          // the JS engine embedded in Adobe products requires returning the `match`
          // string in order to produce the correct `offset` value
          return match;
        });
  
        source += "';\n";
  
        // if `variable` is not specified, wrap a with-statement around the generated
        // code to add the data object to the top of the scope chain
        var variable = options.variable,
            hasVariable = variable;
  
        if (!hasVariable) {
          variable = 'obj';
          source = 'with (' + variable + ') {\n' + source + '\n}\n';
        }
        // cleanup code by stripping empty strings
        source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
          .replace(reEmptyStringMiddle, '$1')
          .replace(reEmptyStringTrailing, '$1;');
  
        // frame code as the function body
        source = 'function(' + variable + ') {\n' +
          (hasVariable ? '' : variable + ' || (' + variable + ' = {});\n') +
          "var __t, __p = '', __e = _.escape" +
          (isEvaluating
            ? ', __j = Array.prototype.join;\n' +
              "function print() { __p += __j.call(arguments, '') }\n"
            : ';\n'
          ) +
          source +
          'return __p\n}';
  
        // Use a sourceURL for easier debugging.
        // http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl
        var sourceURL = '\n/*\n//# sourceURL=' + (options.sourceURL || '/lodash/template/source[' + (templateCounter++) + ']') + '\n*/';
  
        try {
          var result = Function(importsKeys, 'return ' + source + sourceURL).apply(undefined, importsValues);
        } catch(e) {
          e.source = source;
          throw e;
        }
        if (data) {
          return result(data);
        }
        // provide the compiled function's source by its `toString` method, in
        // supported environments, or the `source` property as a convenience for
        // inlining compiled templates during the build process
        result.source = source;
        return result;
      }
  
      /**
       * Executes the callback `n` times, returning an array of the results
       * of each callback execution. The callback is bound to `thisArg` and invoked
       * with one argument; (index).
       *
       * @static
       * @memberOf _
       * @category Utilities
       * @param {number} n The number of times to execute the callback.
       * @param {Function} callback The function called per iteration.
       * @param {*} [thisArg] The `this` binding of `callback`.
       * @returns {Array} Returns an array of the results of each `callback` execution.
       * @example
       *
       * var diceRolls = _.times(3, _.partial(_.random, 1, 6));
       * // => [3, 6, 4]
       *
       * _.times(3, function(n) { mage.castSpell(n); });
       * // => calls `mage.castSpell(n)` three times, passing `n` of `0`, `1`, and `2` respectively
       *
       * _.times(3, function(n) { this.cast(n); }, mage);
       * // => also calls `mage.castSpell(n)` three times
       */
      function times(n, callback, thisArg) {
        n = (n = +n) > -1 ? n : 0;
        var index = -1,
            result = Array(n);
  
        callback = baseCreateCallback(callback, thisArg, 1);
        while (++index < n) {
          result[index] = callback(index);
        }
        return result;
      }
  
      /**
       * The inverse of `_.escape` this method converts the HTML entities
       * `&amp;`, `&lt;`, `&gt;`, `&quot;`, and `&#39;` in `string` to their
       * corresponding characters.
       *
       * @static
       * @memberOf _
       * @category Utilities
       * @param {string} string The string to unescape.
       * @returns {string} Returns the unescaped string.
       * @example
       *
       * _.unescape('Fred, Barney &amp; Pebbles');
       * // => 'Fred, Barney & Pebbles'
       */
      function unescape(string) {
        return string == null ? '' : String(string).replace(reEscapedHtml, unescapeHtmlChar);
      }
  
      /**
       * Generates a unique ID. If `prefix` is provided the ID will be appended to it.
       *
       * @static
       * @memberOf _
       * @category Utilities
       * @param {string} [prefix] The value to prefix the ID with.
       * @returns {string} Returns the unique ID.
       * @example
       *
       * _.uniqueId('contact_');
       * // => 'contact_104'
       *
       * _.uniqueId();
       * // => '105'
       */
      function uniqueId(prefix) {
        var id = ++idCounter;
        return String(prefix == null ? '' : prefix) + id;
      }
  
      /*--------------------------------------------------------------------------*/
  
      /**
       * Creates a `lodash` object that wraps the given value with explicit
       * method chaining enabled.
       *
       * @static
       * @memberOf _
       * @category Chaining
       * @param {*} value The value to wrap.
       * @returns {Object} Returns the wrapper object.
       * @example
       *
       * var characters = [
       *   { 'name': 'barney',  'age': 36 },
       *   { 'name': 'fred',    'age': 40 },
       *   { 'name': 'pebbles', 'age': 1 }
       * ];
       *
       * var youngest = _.chain(characters)
       *     .sortBy('age')
       *     .map(function(chr) { return chr.name + ' is ' + chr.age; })
       *     .first()
       *     .value();
       * // => 'pebbles is 1'
       */
      function chain(value) {
        value = new lodashWrapper(value);
        value.__chain__ = true;
        return value;
      }
  
      /**
       * Invokes `interceptor` with the `value` as the first argument and then
       * returns `value`. The purpose of this method is to "tap into" a method
       * chain in order to perform operations on intermediate results within
       * the chain.
       *
       * @static
       * @memberOf _
       * @category Chaining
       * @param {*} value The value to provide to `interceptor`.
       * @param {Function} interceptor The function to invoke.
       * @returns {*} Returns `value`.
       * @example
       *
       * _([1, 2, 3, 4])
       *  .tap(function(array) { array.pop(); })
       *  .reverse()
       *  .value();
       * // => [3, 2, 1]
       */
      function tap(value, interceptor) {
        interceptor(value);
        return value;
      }
  
      /**
       * Enables explicit method chaining on the wrapper object.
       *
       * @name chain
       * @memberOf _
       * @category Chaining
       * @returns {*} Returns the wrapper object.
       * @example
       *
       * var characters = [
       *   { 'name': 'barney', 'age': 36 },
       *   { 'name': 'fred',   'age': 40 }
       * ];
       *
       * // without explicit chaining
       * _(characters).first();
       * // => { 'name': 'barney', 'age': 36 }
       *
       * // with explicit chaining
       * _(characters).chain()
       *   .first()
       *   .pick('age')
       *   .value();
       * // => { 'age': 36 }
       */
      function wrapperChain() {
        this.__chain__ = true;
        return this;
      }
  
      /**
       * Produces the `toString` result of the wrapped value.
       *
       * @name toString
       * @memberOf _
       * @category Chaining
       * @returns {string} Returns the string result.
       * @example
       *
       * _([1, 2, 3]).toString();
       * // => '1,2,3'
       */
      function wrapperToString() {
        return String(this.__wrapped__);
      }
  
      /**
       * Extracts the wrapped value.
       *
       * @name valueOf
       * @memberOf _
       * @alias value
       * @category Chaining
       * @returns {*} Returns the wrapped value.
       * @example
       *
       * _([1, 2, 3]).valueOf();
       * // => [1, 2, 3]
       */
      function wrapperValueOf() {
        return this.__wrapped__;
      }
  
      /*--------------------------------------------------------------------------*/
  
      // add functions that return wrapped values when chaining
      lodash.after = after;
      lodash.assign = assign;
      lodash.at = at;
      lodash.bind = bind;
      lodash.bindAll = bindAll;
      lodash.bindKey = bindKey;
      lodash.chain = chain;
      lodash.compact = compact;
      lodash.compose = compose;
      lodash.constant = constant;
      lodash.countBy = countBy;
      lodash.create = create;
      lodash.createCallback = createCallback;
      lodash.curry = curry;
      lodash.debounce = debounce;
      lodash.defaults = defaults;
      lodash.defer = defer;
      lodash.delay = delay;
      lodash.difference = difference;
      lodash.filter = filter;
      lodash.flatten = flatten;
      lodash.forEach = forEach;
      lodash.forEachRight = forEachRight;
      lodash.forIn = forIn;
      lodash.forInRight = forInRight;
      lodash.forOwn = forOwn;
      lodash.forOwnRight = forOwnRight;
      lodash.functions = functions;
      lodash.groupBy = groupBy;
      lodash.indexBy = indexBy;
      lodash.initial = initial;
      lodash.intersection = intersection;
      lodash.invert = invert;
      lodash.invoke = invoke;
      lodash.keys = keys;
      lodash.map = map;
      lodash.mapValues = mapValues;
      lodash.max = max;
      lodash.memoize = memoize;
      lodash.merge = merge;
      lodash.min = min;
      lodash.omit = omit;
      lodash.once = once;
      lodash.pairs = pairs;
      lodash.partial = partial;
      lodash.partialRight = partialRight;
      lodash.pick = pick;
      lodash.pluck = pluck;
      lodash.property = property;
      lodash.pull = pull;
      lodash.range = range;
      lodash.reject = reject;
      lodash.remove = remove;
      lodash.rest = rest;
      lodash.shuffle = shuffle;
      lodash.sortBy = sortBy;
      lodash.tap = tap;
      lodash.throttle = throttle;
      lodash.times = times;
      lodash.toArray = toArray;
      lodash.transform = transform;
      lodash.union = union;
      lodash.uniq = uniq;
      lodash.values = values;
      lodash.where = where;
      lodash.without = without;
      lodash.wrap = wrap;
      lodash.xor = xor;
      lodash.zip = zip;
      lodash.zipObject = zipObject;
  
      // add aliases
      lodash.collect = map;
      lodash.drop = rest;
      lodash.each = forEach;
      lodash.eachRight = forEachRight;
      lodash.extend = assign;
      lodash.methods = functions;
      lodash.object = zipObject;
      lodash.select = filter;
      lodash.tail = rest;
      lodash.unique = uniq;
      lodash.unzip = zip;
  
      // add functions to `lodash.prototype`
      mixin(lodash);
  
      /*--------------------------------------------------------------------------*/
  
      // add functions that return unwrapped values when chaining
      lodash.clone = clone;
      lodash.cloneDeep = cloneDeep;
      lodash.contains = contains;
      lodash.escape = escape;
      lodash.every = every;
      lodash.find = find;
      lodash.findIndex = findIndex;
      lodash.findKey = findKey;
      lodash.findLast = findLast;
      lodash.findLastIndex = findLastIndex;
      lodash.findLastKey = findLastKey;
      lodash.has = has;
      lodash.identity = identity;
      lodash.indexOf = indexOf;
      lodash.isArguments = isArguments;
      lodash.isArray = isArray;
      lodash.isBoolean = isBoolean;
      lodash.isDate = isDate;
      lodash.isElement = isElement;
      lodash.isEmpty = isEmpty;
      lodash.isEqual = isEqual;
      lodash.isFinite = isFinite;
      lodash.isFunction = isFunction;
      lodash.isNaN = isNaN;
      lodash.isNull = isNull;
      lodash.isNumber = isNumber;
      lodash.isObject = isObject;
      lodash.isPlainObject = isPlainObject;
      lodash.isRegExp = isRegExp;
      lodash.isString = isString;
      lodash.isUndefined = isUndefined;
      lodash.lastIndexOf = lastIndexOf;
      lodash.mixin = mixin;
      lodash.noConflict = noConflict;
      lodash.noop = noop;
      lodash.now = now;
      lodash.parseInt = parseInt;
      lodash.random = random;
      lodash.reduce = reduce;
      lodash.reduceRight = reduceRight;
      lodash.result = result;
      lodash.runInContext = runInContext;
      lodash.size = size;
      lodash.some = some;
      lodash.sortedIndex = sortedIndex;
      lodash.template = template;
      lodash.unescape = unescape;
      lodash.uniqueId = uniqueId;
  
      // add aliases
      lodash.all = every;
      lodash.any = some;
      lodash.detect = find;
      lodash.findWhere = find;
      lodash.foldl = reduce;
      lodash.foldr = reduceRight;
      lodash.include = contains;
      lodash.inject = reduce;
  
      mixin(function() {
        var source = {}
        forOwn(lodash, function(func, methodName) {
          if (!lodash.prototype[methodName]) {
            source[methodName] = func;
          }
        });
        return source;
      }(), false);
  
      /*--------------------------------------------------------------------------*/
  
      // add functions capable of returning wrapped and unwrapped values when chaining
      lodash.first = first;
      lodash.last = last;
      lodash.sample = sample;
  
      // add aliases
      lodash.take = first;
      lodash.head = first;
  
      forOwn(lodash, function(func, methodName) {
        var callbackable = methodName !== 'sample';
        if (!lodash.prototype[methodName]) {
          lodash.prototype[methodName]= function(n, guard) {
            var chainAll = this.__chain__,
                result = func(this.__wrapped__, n, guard);
  
            return !chainAll && (n == null || (guard && !(callbackable && typeof n == 'function')))
              ? result
              : new lodashWrapper(result, chainAll);
          };
        }
      });
  
      /*--------------------------------------------------------------------------*/
  
      /**
       * The semantic version number.
       *
       * @static
       * @memberOf _
       * @type string
       */
      lodash.VERSION = '2.4.1';
  
      // add "Chaining" functions to the wrapper
      lodash.prototype.chain = wrapperChain;
      lodash.prototype.toString = wrapperToString;
      lodash.prototype.value = wrapperValueOf;
      lodash.prototype.valueOf = wrapperValueOf;
  
      // add `Array` functions that return unwrapped values
      forEach(['join', 'pop', 'shift'], function(methodName) {
        var func = arrayRef[methodName];
        lodash.prototype[methodName] = function() {
          var chainAll = this.__chain__,
              result = func.apply(this.__wrapped__, arguments);
  
          return chainAll
            ? new lodashWrapper(result, chainAll)
            : result;
        };
      });
  
      // add `Array` functions that return the existing wrapped value
      forEach(['push', 'reverse', 'sort', 'unshift'], function(methodName) {
        var func = arrayRef[methodName];
        lodash.prototype[methodName] = function() {
          func.apply(this.__wrapped__, arguments);
          return this;
        };
      });
  
      // add `Array` functions that return new wrapped values
      forEach(['concat', 'slice', 'splice'], function(methodName) {
        var func = arrayRef[methodName];
        lodash.prototype[methodName] = function() {
          return new lodashWrapper(func.apply(this.__wrapped__, arguments), this.__chain__);
        };
      });
  
      return lodash;
    }
  
    /*--------------------------------------------------------------------------*/
  
    // expose Lo-Dash
    var _ = runInContext();
  
    // some AMD build optimizers like r.js check for condition patterns like the following:
    if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
      // Expose Lo-Dash to the global object even when an AMD loader is present in
      // case Lo-Dash is loaded with a RequireJS shim config.
      // See http://requirejs.org/docs/api.html#config-shim
      root._ = _;
  
      // define as an anonymous module so, through path mapping, it can be
      // referenced as the "underscore" module
      define(function() {
        return _;
      });
    }
    // check for `exports` after `define` in case a build optimizer adds an `exports` object
    else if (freeExports && freeModule) {
      // in Node.js or RingoJS
      if (moduleExports) {
        (freeModule.exports = _)._ = _;
      }
      // in Narwhal or Rhino -require
      else {
        freeExports._ = _;
      }
    }
    else {
      // in a browser or Rhino
      root._ = _;
    }
  }.call(this));
  
  }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  },{}],21:[function(_dereq_,module,exports){
  (function (process){
  // Determines wether actions should be deferred for processing
  exports.defer = false;
  
  
  /**
   * Defer a function call momentairly.
   * @param {Function} fn
   */
  function deferred(fn) {
    if (exports.defer === true) {
      process.nextTick(fn);
    } else {
      fn();
    }
  }
  
  
  /**
   * Stringify JSON and catch any possible exceptions.
   * @param {Object}    json
   * @param {Function}  [replacer]
   * @param {Number}    [spaces]
   * @param {Function}  callback
   */
  exports.stringify = function (/*json, replacer, spaces, callback*/) {
    var args = Array.prototype.slice.call(arguments)
      , callback = args.splice(args.length - 1, args.length)[0];
  
    deferred(function() {
      try {
        return callback(null, JSON.stringify.apply(null, args));
      } catch (e) {
        return callback(e, null);
      }
    });
  };
  
  
  /**
   * Parse string of JSON and catch any possible exceptions.
   * @param {String}    json
   * @param {Function}  [reviver]
   * @param {Function}  callback
   */
  exports.parse = function (/*json, reviver, callback*/) {
    var args = Array.prototype.slice.call(arguments)
      , callback = args.splice(args.length - 1, args.length)[0];
  
    deferred(function() {
      try {
        return callback(null, JSON.parse.apply(null, args));
      } catch (e) {
        return callback(e, null);
      }
    });
  };
  }).call(this,_dereq_("FWaASH"))
  },{"FWaASH":14}]},{},[5])
  (5)
  });