text: (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);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.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(require,module,exports){
  var Hogan = require("hogan.js");; this["Templates"] = this["Templates"] || {};
  this["Templates"]["commons/layout"] = new Hogan.Template(function(c,p,i){var _=this;_.b(i=i||"");_.b("<!DOCTYPE html><html lang=\"en-US\" class=\"");_.b(_.v(_.f("env",c,p,0)));_.b("\" data-page=\"");_.b(_.v(_.f("pageName",c,p,0)));_.b("\"><head><!--[if IE 7]><script>document.documentElement.className += \" ie ie7\";</script><![endif]--><!--[if IE 8]><script>document.documentElement.className += \" ie ie8\";</script><![endif]--><!--[if IE 9]><script>document.documentElement.className += \" ie ie9\";</script><![endif]--><!--[if IE]><script src=\"/js/html5shiv.js\"></script><![endif]--><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no\"><meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\"><meta name=\"msapplication-tap-highlight\" content=\"no\"><title>");_.b(_.v(_.f("appName",c,p,0)));_.b("</title>");if(_.s(_.f("styles",c,p,1),c,p,0,709,745,"{{ }}")){_.rs(c,p,function(c,p,_){_.b("<link rel=\"stylesheet\" href=\"");_.b(_.v(_.d(".",c,p,0)));_.b("\">");});c.pop();}_.b("<script src=\"/js/jquery-1.10.2.min.js\" type=\"text/javascript\"></script></head><body><div id=\"site-wrapper\" role=\"application\"><header id=\"header\" role=\"banner\">");_.b(_.t(_.f("widget-header",c,p,0)));_.b("</header><main id=\"content\" role=\"main\">");_.b(_.t(_.f("widget-content",c,p,0)));_.b("</main><div id=\"loader\" role=\"complementary\"><img src=\"/img/loader_blue_32.gif\" class=\"loader js-loader\"></div><footer id=\"footer\" role=\"contentinfo\">");_.b(_.t(_.f("widget-footer",c,p,0)));_.b("</footer></div>");if(_.s(_.f("scripts",c,p,1),c,p,0,1191,1243,"{{ }}")){_.rs(c,p,function(c,p,_){_.b("<script type=\"text/javascript\" src=\"");_.b(_.v(_.d(".",c,p,0)));_.b("\"></script>");});c.pop();}_.b("</body></html>");return _.fl();;});
  this["Templates"]["widget-content/about"] = new Hogan.Template(function(c,p,i){var _=this;_.b(i=i||"");_.b("<div class=\"info-container\">");_.b(_.t(_.f("widget-info",c,p,0)));_.b("</div><div class=\"go-back-container\"><a href=\"javascript:void(0)\" redirect=\"/\">");_.b(_.v(_.f("termGoBack",c,p,0)));_.b("</a></div>");return _.fl();;});
  this["Templates"]["widget-content/contact"] = new Hogan.Template(function(c,p,i){var _=this;_.b(i=i||"");_.b("<div class=\"info-container\">");_.b(_.t(_.f("widget-info",c,p,0)));_.b("</div><div class=\"social-container\">");_.b(_.t(_.f("social-details",c,p,0)));_.b("</div><div class=\"go-back-container\"><a href=\"javascript:void(0)\" redirect=\"/\">");_.b(_.v(_.f("termGoBack",c,p,0)));_.b("</a></div>");return _.fl();;});
  this["Templates"]["widget-content/home"] = new Hogan.Template(function(c,p,i){var _=this;_.b(i=i||"");_.b("<div class=\"links-container\">");_.b(_.t(_.f("widget-links",c,p,0)));_.b("</div>");return _.fl();;});
  this["Templates"]["widget-footer/main"] = new Hogan.Template(function(c,p,i){var _=this;_.b(i=i||"");_.b("<p>");_.b(_.t(_.f("text",c,p,0)));_.b("</p>");return _.fl();;});
  this["Templates"]["widget-header/main"] = new Hogan.Template(function(c,p,i){var _=this;_.b(i=i||"");_.b("<h2><a href=\"javascript:void(0)\" redirect=\"/\">");_.b(_.v(_.f("title",c,p,0)));_.b("</a></h2>");return _.fl();;});
  this["Templates"]["widget-info/main"] = new Hogan.Template(function(c,p,i){var _=this;_.b(i=i||"");_.b("<p class=\"info\">");_.b(_.t(_.f("text",c,p,0)));_.b("</p>");return _.fl();;});
  this["Templates"]["widget-links/main"] = new Hogan.Template(function(c,p,i){var _=this;_.b(i=i||"");_.b("<ul class=\"list-links\">");if(_.s(_.f("items",c,p,1),c,p,0,33,116,"{{ }}")){_.rs(c,p,function(c,p,_){_.b("<li><a href=\"javascript:void(0)\" redirect=\"/");_.b(_.v(_.f("page",c,p,0)));_.b("\">Navigate to ");_.b(_.v(_.f("name",c,p,0)));_.b("</a></li>");});c.pop();}_.b("</ul>");return _.fl();;});
  this["Templates"]["widget-social/main"] = new Hogan.Template(function(c,p,i){var _=this;_.b(i=i||"");_.b("<div></div>");return _.fl();;});
  
  if(typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
    module.exports = this["Templates"];
  }
  },{"hogan.js":76}],2:[function(require,module,exports){
  // Application's startup (an entry point) on a client side
  // ------------
  (function appStartupClientSide(window, $, undefined) {
    var wireup = require('./app.wireup.js');
    var container = wireup(window, $, false);
  
    // Prepare the environment
    if (!('app' in window)) {
      window.app = container.resolve('startup');
    }
  
    // logging all "loaded" events, just for fun or debugging purposes
    window.app.bus.on(window.app.namespace + '::*::loaded', function (data) {
      console.log('loaded: ', data);
    });
  
    // init our app on a page load
    $(function () {
      var obj = { id: window.app.namespace };
      window.app.bus.emit(window.app.namespace + '::routing::init', obj, function () {
        window.app.bus.emit(window.app.namespace + '::app::loaded', obj);
      })
    });
  })(window, window.jQuery);
  },{"./app.wireup.js":3}],3:[function(require,module,exports){
  // Application's wire-up
  // ------------
  (function appWireup(module) {
    'use strict';
  
    module.exports = function (window, $, isServerSide, undefined) {
      var Nodeject = require('nodeject');
      var _ = require('underscore');
      var EventEmitter2 = require('eventemitter2').EventEmitter2;
      var director = require('director');
      var templates = require('../build/templates.js');
      var async = require('async');
      var http = require('http');
      var https = require('https');
  
      var container = new Nodeject({ singleton: true });
      container
        .define({ name: 'window', wrap: { resolve: window || null } })
        .define({ name: '$', wrap: { resolve: $ || null } })
        .define({ name: '_', wrap: { resolve: _ } })
        .define({ name: 'router', wrap: { resolve: director } })
        .define({ name: 'templates', wrap: { resolve: templates } })
        .define({ name: 'async', wrap: { resolve: async } })
        .define({ name: 'http', wrap: { resolve: http } })
        .define({ name: 'https', wrap: { resolve: https } })
        .define({
          name: 'app', type: function () {
            return {
              bus: new EventEmitter2({
                wildcard: true,
                delimiter: '::'
              }),
              isServerSide: isServerSide,
              namespace: 'spa-sushi',
              attrPage: 'data-page'
            };
          }
        })
        .define({ name: 'bus', wrap: { resolve: 'bus', context: 'app' } })
        .define({
          name: 'startup',
          type: function (app, templates) {
            (function resolveDependencies(container, app) {
              var categories = ['commons', 'presenters', 'controllers', 'wireups'];
              categories.forEach(function (category) {
                app[category] = container.resolve({
                  category: category,
                  format: 'literal'
                });
              });
            })(container, app);
  
            // Assign the container
            app.container = container;
            app.templates = templates;
  
            // Return the initialized app
            return app;
          },
          deps: ['app', 'templates']
        });
  
      function addToList(aggr, obj) {
        aggr = aggr || {};
        if (obj) {
          _.keys(obj || []).forEach(function (category) {
            aggr[category] = aggr[category] || [];
            aggr[category] = aggr[category].concat(obj[category]);
          });
        }
        return aggr;
      }
  
      // Wire up features
      var configs = {};
  
      var commons = require('./commons/configure.js');
      addToList(configs, commons.configure(isServerSide));
      var wHeader = require('./widget-header/configure.js');
      addToList(configs, wHeader);
      var wContent = require('./widget-content/configure.js');
      addToList(configs, wContent);
      var wFooter = require('./widget-footer/configure.js');
      addToList(configs, wFooter);
  
      var wInfo = require('./widget-info/configure.js');
      addToList(configs, wInfo);
      var wLinks = require('./widget-links/configure.js');
      addToList(configs, wLinks);
      var wSocial = require('./widget-social/configure.js');
      addToList(configs, wSocial);
  
      _.keys(configs || []).forEach(function (category) {
        (configs[category] || []).forEach(function (item) {
          container.define(_.extend({ category: category }, item));
        });
      });
  
      return container;
    };
  })(module);
  
  },{"../build/templates.js":1,"./commons/configure.js":4,"./widget-content/configure.js":14,"./widget-footer/configure.js":19,"./widget-header/configure.js":23,"./widget-info/configure.js":27,"./widget-links/configure.js":31,"./widget-social/configure.js":35,"async":39,"director":40,"eventemitter2":41,"http":47,"https":51,"nodeject":78,"underscore":79}],4:[function(require,module,exports){
  (function commonConfigure(module) {
    'use strict';
  
    module.exports = {
      configure: function (isServerSide) {
        var result = {
          'commons': [
            {
              name: 'browser',
              type: require('./js/browser.js').init,
              deps: ['app', 'window', '$']
            },
            {
              name: 'logging',
              type: require('./js/logging.js').init,
              deps: ['app', '_', 'ajax', 'browser']
            },
            {
              name: 'page',
              type: require('./js/page.js').init,
              deps: ['app', 'window', '$', '_', 'async', 'browser']
            },
            {
              name: 'routes',
              type: require('./js/routes.js').init,
              deps: []
            },
            {
              name: 'utils',
              type: require('./js/utils.js').init,
              deps: ['app', 'window', '$', '_', 'browser']
            }
          ]
        };
  
        if (isServerSide) {
          result['commons'] = result['commons'].concat([
            {
              name: 'ajax',
              type: require('./js/ajax-server.js').init,
              deps: ['app', 'window', '$', '_', 'http', 'https']
            },
            {
              name: 'routing',
              type: require('./js/routing-server.js').init,
              deps: ['app', 'window', '$', '_', 'ajax', 'browser', 'router', 'routes', 'page']
            }
          ]);
        } else {
          result['commons'] = result['commons'].concat([
            {
              name: 'ajax',
              type: require('./js/ajax-client.js').init,
              deps: ['app', 'window', '$', '_', 'http', 'https']
            },
            {
              name: 'routing',
              type: require('./js/routing-client.js').init,
              deps: ['app', 'window', '$', '_', 'ajax', 'browser', 'router', 'routes', 'page']
            }
          ]);
        }
  
        return result;
      }
    };
  })(module);
  
  },{"./js/ajax-client.js":5,"./js/ajax-server.js":6,"./js/browser.js":7,"./js/logging.js":8,"./js/page.js":9,"./js/routes.js":10,"./js/routing-client.js":11,"./js/routing-server.js":12,"./js/utils.js":13}],5:[function(require,module,exports){
  (function ajaxClientInit(module) {
      'use strict';
  
      module.exports = {
          init: function (app, window, $, _, http, https, undefined) {
              var makeRequest = function (options, cb) {
                  $.ajax(_.defaults(options, {
                      headers: {},
                      dataType: 'json',
                      cache: false,
                      success: function (response) {
                          if (cb && typeof cb === 'function') {
                              cb(null, response);
                          }
                      },
                      error: function (error) {
                          if (cb && typeof cb === 'function') {
                              cb(error, null);
                          }
                      }
                  }));
              };
  
              var ajax = {
                  'get': function (options, cb) {
                      makeRequest({
                          url: options.url,
                          data: options.data,
                          contentType: options.contentType || 'application/json;charset=utf-8',
                          type: 'get'
                      }, cb);
                  },
                  'post': function (options, cb) {
                      makeRequest({
                          url: options.url,
                          data: options.data,
                          contentType: options.contentType || 'application/x-www-form-urlencoded; charset=UTF-8',
                          type: 'post'
                      }, cb);
                  },
                  'delete': function (options, cb) {
                      makeRequest({
                          url: options.url,
                          data: options.data,
                          contentType: options.contentType || 'application/x-www-form-urlencoded; charset=UTF-8',
                          type: 'delete'
                      }, cb);
                  }
              };
  
              /* enable support of CORS */
              $.support.cors = true;
  
              return ajax;
          }
      };
  })(module);
  },{}],6:[function(require,module,exports){
  (function ajaxServerInit(module) {
      'use strict';
  
      module.exports = {
          init: function (app, window, $, _, http, https, undefined) {
              var isJson = function (text) {
                  return (/^[\],:{}\s]*$/.test(text.replace(/\\["\\\/bfnrtu]/g, '@').
                      replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
                      replace(/(?:^|:|,)(?:\s*\[)+/g, '')));
              };
  
              var makeRequest = function (options, cb) {
                  var protocol = options.port === 443 ? https : http;
  
                  // TODO: put it in config.json
                  if (!options.hostname) {
                      options.hostname = 'localhost';
                      options.port = 7889;
                  }
  
                  if (options.url && !options.path) {
                      options.path = options.url;
                      delete options.url;
                  }
  
                  if (options.data) {
                      options.path = options.path + _.reduce(options.data, function (memo, value, name) {
                          return memo + ((_.isNull(value) || _.isUndefined(value) || value === '') ? '' : (name + '=' + value + '&'));
                      }, '?');
                      delete options.data;
                  }
  
                  protocol
                      .request(options, function (apiRes) {
                          var data = '';
  
                          apiRes.on('data', function (chunk) {
                              data += chunk;
                          });
  
                          apiRes.on('end', function (a, b) {
                              if (cb && typeof cb === 'function') {
                                  if (isJson(data)) {
                                      cb(null, JSON.parse(data));
                                  } else {
                                      cb({ error: { code: '400', message: 'returned data not Json format', description: 'returned data not Json format' } })
                                  }
                              }
                          });
  
                          apiRes.on('clientError', function (emp, dmp) {
                              console.log("emp", emp);
                              console.log("dmp", dmp);
                          });
                      })
                      .on('error', function (err) {
                          if (cb && typeof cb === 'function') {
                              cb(err, null);
                          }
                      })
                      .end();
              };
  
              var ajax = {
                  'get': function (options, cb) {
                      if (options) {
                          options.method = 'GET';
                          makeRequest(options, cb);
                      }
                  },
                  'post': function (options, cb) {
                      if (options) {
                          options.method = 'POST';
                          makeRequest(options, cb);
                      }
                  },
                  'put': function (options, cb) {
                      if (options) {
                          options.method = 'PUT';
                          makeRequest(options, cb);
                      }
                  },
                  'delete': function (options, cb) {
                      if (options) {
                          options.method = 'DELETE';
                          makeRequest(options, cb);
                      }
                  }
              };
  
              return ajax;
          }
      };
  })(module);
  },{}],7:[function(require,module,exports){
  (function browserInit(module) {
      'use strict';
  
      module.exports = {
          init: function (app, window, $, undefined) {
              var browser = {};
  
              var html = (function () {
                  var result = null;
                  if (window && window.document && window.document.documentElement) {
                      result = $(window.document.documentElement);
                      if (result.length === 0) {
                          result = $('html');
                      }
                  }
                  return result;
              })();
  
              var getUAMatch = function (ua) {
                  var match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
                      /(webkit)[ \/]([\w.]+)/.exec(ua) ||
                      /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
                      /(msie) ([\w.]+)/.exec(ua) ||
                      /(trident).*(rv[ :][\w.]+)/.exec(ua) ||
                      ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) ||
                      [];
                  
                  var result = {
                      browser: match[1] || '',
                      version: match[2] || '0'
                  };
  
                  /* special stuff for IE11 detection */
                  result.browser = (result.browser === 'trident' ? 'msie' : result.browser);
                  result.version = (result.version === 'rv:11.0' ? '11' : result.version);
  
                  return result;
              };
  
              // Set current browser info
              // ----------------
              (function setBrowserInfo(browser) {
                  if (window && window.navigator && html) {
                      var uaMatch = getUAMatch(window.navigator.userAgent.toLowerCase());
  
                      var uaBrowser = (function (matched) {
                          var result = {};
  
                          if (matched.browser) {
                              result[matched.browser] = true;
                              result.version = matched.version;
                          }
  
                          /* Chrome is Webkit, but Webkit is also Safari */
                          if (result.chrome) {
                              result.webkit = true;
                          } else if (result.webkit) {
                              result.safari = true;
                          }
  
                          return result;
                      })(uaMatch);
  
                      var setFlag = function (browser, html, prop) {
                          browser[prop] = true;
                          html.addClass(prop);
                      };
  
                      if (uaBrowser.msie) {
                          if (uaBrowser.version) {
                              setFlag(browser, html, 'ie' + (+uaBrowser.version).toString());
                          }
                          setFlag(browser, html, 'ie');
                      } else if (uaBrowser.webkit) {
                          setFlag(browser, html, 'webkit');
                          if (uaBrowser.safari) {
                              setFlag(browser, html, 'safari');
                          } else if (uaBrowser.chrome) {
                              setFlag(browser, html, 'chrome');
                          }
                      } else if (uaBrowser.mozilla) {
                          setFlag(browser, html, 'mozilla');
                      }
                  }
              })(browser);
  
              // Set current operating system info
              // ----------------
              (function setOsInfo(browser) {
                  if (window && window.navigator && html) {
                      var platform = window.navigator.platform.toLowerCase();
                      browser.os = {
                          isWin: platform.indexOf('win') !== -1,
                          isMac: platform.indexOf('mac') !== -1
                      };
                      if (browser.os.isMac) {
                          html.addClass('mac');
                      } else if (browser.os.isWin) {
                          html.addClass('win');
                      }
                  }
              })(browser);
  
              // Init query string func
              // ----------------
              (function initQueryString(browser) {
                  if (window && window.RegExp) {
                      browser.qs = function (name) {
                          name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
                          var regex = new window.RegExp("[\\?&]" + name + "=([^&#]*)");
                          var results = regex.exec(window.location.search);
                          return results === null ? null : decodeURIComponent(results[1].replace(/\+/g, " "));
                      };
                  }
              })(browser);
  
              // Init media queries func
              // ----------------
              (function initMedia(browser) {
                  if (window) {
                      browser.media = (function () {
                          var getBodyContent = function () {
                              if ('getComputedStyle' in window) {
                                  return window.getComputedStyle(document.body, ':after').getPropertyValue('content')
                                      .replace(/"/g, '')
                                      .replace(/\'/g, '');
                              } else {
                                  return 'desktop';
                              }
                          };
                          return {
                              isMobilePortrait: function () {
                                  return getBodyContent() === 'mobilePortrait';
                              },
                              isMobileLandscape: function () {
                                  return getBodyContent() === 'mobileLandscape';
                              },
                              isTablet: function () {
                                  return getBodyContent() === 'tablet';
                              },
                              isDesktop: function () {
                                  return getBodyContent() === 'desktop';
                              },
                              getCurrent: function () {
                                  return getBodyContent();
                              }
                          };
                      })();
                  }
              })(browser);
  
              // Init cookie func
              // ----------------
              (function initCookie(browser) {
                  if (window && window.location && window.document) {
                      var getDomain = function () {
                          return window.location.host.replace('www.', '');
                      };
  
                      browser.setCookie = function (name, value, path, expires, domain) {
                          if (name) {
                              name = name.toUpperCase();
                          }
                          var newCookie = name + '=' + value + ';';
                          newCookie += ' path=' + (path || '/');
                          if (expires) {
                              newCookie += '; expires=' + expires;
                          }
                          newCookie += '; domain=' + (domain || getDomain());
                          window.document.cookie = newCookie;
                          return true;
                      };
  
                      browser.getCookie = function (name) {
                          if (name) {
                              name = name.toUpperCase();
                              var i, x, y, cookies = window.document.cookie.split(";");
                              for (i = 0; i < cookies.length; i++) {
                                  x = cookies[i].substr(0, cookies[i].indexOf("="));
                                  y = cookies[i].substr(cookies[i].indexOf("=") + 1);
                                  x = x.replace(/^\s+|\s+$/g, "");
                                  if (x === name) {
                                      return unescape(y);
                                  }
                              }
                          }
                          return null;
                      };
  
                      browser.removeCookie = function (name) {
                          return browser.setCookie(name, '0', null, new Date(-1));
                      };
                  }
              })(browser);
  
              // Detect browser features
              // ----------------
              (function initFeatures(browser) {
                  if (window && window.navigator && html) {
                      var agent = window.navigator.userAgent || window.navigator.vendor || window.opera;
                      browser.features = {
                          sessionStorage: !!('sessionStorage' in window),
                          mutationObserver: !!(('MutationObserver' in window) || ('WebKitMutationObserver' in window)),
                          touchDevice: !!(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch),
                          html5history: ('history' in window) && ('pushState' in (window.history || {})),
                          isMobileDevice: (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(agent) ||
                              /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(agent.substr(0, 4)))
                      };
                      html
                          .addClass(browser.features.sessionStorage ? 'sessionStorage' : 'no-sessionStorage')
                          .addClass(browser.features.touchDevice ? 'touch' : 'no-touch')
                          .addClass(browser.features.html5history ? 'html5history' : 'no-html5history')
                          .addClass(browser.features.isMobileDevice ? 'mobile' : 'desktop');
                  }
              })(browser);
  
              // Init other func
              // ----------------
              (function initOtherFunctions(browser) {
                  if (window && window.document && window.navigator) {
                      browser.getViewPort = function () {
                          var w = window;
                          var d = w.document;
                          var e = d.documentElement;
                          var b = d.getElementsByTagName('body')[0];
                          return {
                              height: w.innerHeight || e.clientHeight || b.clientHeight,
                              width: w.innerWidth || e.clientWidth || b.clientWidth
                          };
                      };
  
                      browser.getInfo = function () {
                          var uaMatch = getUAMatch(window.navigator.userAgent.toLowerCase());
                          var viewPort = browser.getViewPort();
                          return {
                              browser: uaMatch.browser.toLowerCase(),
                              version: uaMatch.version.toLowerCase(),
                              viewPortHeight: viewPort.height,
                              viewPortWidth: viewPort.width,
                              mediaQuery: browser.media.getCurrent(),
                              os: window.navigator.platform.toLowerCase(),
                              device: browser.features.isMobileDevice ? 'mobile' : 'desktop'
                          };
                      };
                  }
              })(browser);
  
              return browser;
          }
      };
  })(module);
  },{}],8:[function(require,module,exports){
  (function loggingInit(module) {
      'use strict';
  
      module.exports = {
          init: function (app, _, ajax, browser, undefined) {
              var logging = {
                  log: function (message, data, cb) {
                      ajax.post({
                          url: '/api/error',
                          data: {
                              message: message,
                              data: _.extend(data, {
                                  url: window.location.href,
                                  browser: ('getInfo' in browser) ? browser.getInfo() : null
                              })
                          }
                      }, cb);
                  }
              };
  
              if (app.bus) {
                  app.bus.on(app.namespace + '::logging::log', function (message, data, cb) {
                      logging.log(message, data, cb);
                  });
              }
  
              return logging;
          }
      };
  })(module);
  },{}],9:[function(require,module,exports){
  (function pageInit(module) {
      'use strict';
  
      var contentSelector = '#site-wrapper';
      var animationTimeout = 250;
  
      module.exports = {
          init: function (app, window, $, _, async, browser, undefined) {
              var getHtml = function () {
                  var html = $(window.document.documentElement);
                  if (html.length === 0) {
                      html = $('html');
                  }
                  return html;
              };
  
              var page = {
                  render: function (data, cb) {
                      if (window && window.document) {
                          getHtml()
                              .find('#content').hide().end()
                              .find('#loader').fadeIn(animationTimeout);
                      }
  
                      var routeData = data.routeData;
                      async.parallel({
                          'widget-header': function (cb) {
                              app.bus.emit(app.namespace + '::widget-header::render', routeData, cb);
                          },
                          'widget-content': function (cb) {
                              app.bus.emit(app.namespace + '::widget-content::render', routeData, cb);
                          },
                          'widget-footer': function (cb) {
                              app.bus.emit(app.namespace + '::widget-footer::render', routeData, cb);
                          }
                      }, function (err, asyncData) {
                          /* server side renders a whole page */
                          if (data && data.server && data.res) {
                              var server = data.server;
                              var res = data.res;
  
                              var html = app.templates['commons/layout'].render(_.extend({
                                  appName: server.get('appName'),
                                  env: server.get('env'),
                                  pageName: routeData.pageName,
                                  styles: ['/css/style.css'],
                                  scripts: ['/js/script.js', '/js/underscore-min.js']
                              }, asyncData));
  
                              console.log('!!! >>>', app.templates['commons/layout'].render({}));
  
                              res.set('Content-Type', 'text/html');
                              res.send(200, html);
                          } else {
                              /* client side renders only main containers */
                              var html = getHtml();
  
                              html
                                  .attr(app.attrPage, routeData.pageName)
                                  .find('#header').html(asyncData['widget-header']).end()
                                  .find('#footer').html(asyncData['widget-footer']).end()
                                  .find('#content').html(asyncData['widget-content']);
  
                              html
                                  .find('#loader').fadeOut(animationTimeout, function () {
                                      html.find('#content').show();
                                      page.wireup();
                                  });
                          }
  
                          app.bus.emit(app.namespace + '::' + routeData.pageName + '::rendered', data);
  
                          if (cb && typeof cb === 'function') {
                              cb(data);
                          }
                      });
                  },
                  renderNotFound: function () {
                      // TODO: not found page implementation
                  },
                  wireup: function (data, cb) {
                      if (window && window.document) {
                          var html = getHtml();
                          var pageName = html.attr(app.attrPage);
                          async.parallel({
                              'widget-header': function (cb) {
                                  app.bus.emit(app.namespace + '::widget-header::wireup', {
                                      pageName: pageName,
                                      container: html.find('#header')
                                  }, function (err, data) {
                                      // nothing here, we cannot use async cb in here
                                      // since cb can be triggered multiple times
                                      // depends on how many wireups we have
                                  });
                                  cb(null, 'widget-header-wired-up');
                              },
                              'widget-content': function (cb) {
                                  app.bus.emit(app.namespace + '::widget-content::wireup', {
                                      pageName: pageName,
                                      container: html.find('#content')
                                  }, function (err, data) {
                                      // nothing here, we cannot use async cb in here
                                      // since cb can be triggered multiple times
                                      // depends on how many wireups we have
                                  });
                                  cb(null, 'widget-content-wired-up');
                              },
                              'widget-footer': function (cb) {
                                  app.bus.emit(app.namespace + '::widget-footer::wireup', {
                                      pageName: pageName,
                                      container: html.find('#footer')
                                  }, function (err, data) {
                                      // nothing here, we cannot use async cb in here
                                      // since cb can be triggered multiple times
                                      // depends on how many wireups we have
                                  });
                                  cb(null, 'widget-footer-wired-up');
                              }
                          }, function (err, asyncData) {
                              if (cb && typeof cb === 'function') {
                                  cb(data);
                              }
                          });
                      }
                  }
              };
  
              if ('bus' in app) {
                  app.bus.on(app.namespace + '::app::loaded', function (data, cb) {
                      page.wireup(data, cb);
                  });
              }
  
              return page;
          }
      };
  })(module);
  },{}],10:[function(require,module,exports){
  (function routesDefinitionInit(module) {
      'use strict';
  
      module.exports = {
          init: function (undefined) {
              return {
                  '/': {
                      routeData: {pageName: 'home'}
                  },
                  '/(home|index)': {
                      routeData: {pageName: 'home'}
                  },
                  '/about': {
                      routeData: {pageName: 'about'}
                  },
                  '/contact': {
                      routeData: {pageName: 'contact'}
                  }
              };
          }
      };
  })(module);
  },{}],11:[function(require,module,exports){
  (function routingClientInit(module) {
      'use strict';
  
      var moduleName = 'routing';
  
      var getRegExSlashOrQueryString = function () {
          return '((\/)|(\\?.*))?';
      };
  
      var getFullDomain = function (location) {
          return location.protocol + '//' + location.host;
      };
  
      module.exports = {
          init: function (app, window, $, _, ajax, browser, router, routesDict, page, undefined) {
              var routing = {
                  router: null,
                  init: function (data, cb) {
                      var routes = _.reduce(routesDict, function (memo, data, route) {
                          memo[route + getRegExSlashOrQueryString()] = function () {
                              page.render(data);
                          };
                          return memo;
                      }, {});
  
                      routing.router = router.Router(routes).configure({
                          //run_handler_in_init: false,
                          html5history: browser.features.html5history,
                          run_handler_in_init: false,
                          notfound: function () {
                              page.render({
                                  routeData: {pageName: 'not-found'}
                              });
                          }
                      }).init();
  
                      var html = $(window.document.documentElement);
                      if (html.length === 0) {
                          html = $('html');
                      }
  
                      html.find('body')
                          .off('click.redirect', '[redirect]')
                          .on('click.redirect', '[redirect]', function (event) {
                              var el = $(event.currentTarget);
                              app.bus.emit(app.namespace + '::routing::navigate', el.attr('redirect'));
                              return true;
                          });
  
                      if (cb && typeof cb === 'function') {
                          cb(data);
                      }
                  }
              };
  
              if ('bus' in app) {
                  app.bus.on(app.namespace + '::' + moduleName + '::init', function (data, cb) {
                      routing.init(data, cb);
                  });
                  app.bus.on(app.namespace + '::' + moduleName + '::navigate', function (url, cb) {
                      if (url) {
                          var domain = getFullDomain(window.location);
                          if (url.indexOf(domain) === 0) {
                              url = url.replace(domain, '');
                          }
                          if (url.indexOf('http:') >= 0 || url.indexOf('https:') >= 0) {
                              /* set a delay before we redirect user to a new page, so tracking can get some time to log */
                              setTimeout(function () { window.location = url; }, 250);
                          } else {
                              routing.router.setRoute(url);
                          }
                      }
                      if (cb && typeof cb === 'function') {
                          cb();
                      }
                  });
              }
  
              return routing;
          }
      };
  })(module);
  },{}],12:[function(require,module,exports){
  (function routingServerInit(module) {
      'use strict';
  
      var moduleName = 'routing';
  
      module.exports = {
          init: function (app, window, $, _, ajax, browser, router, routesDict, page, undefined) {
              var routing = {
                  router: null,
                  init: function (data, cb) {
                      var getServerObject = function (handler) {
                          return {
                              server: data.server,
                              log: data.log,
                              req: handler.req,
                              res: handler.res
                          };
                      };
  
                      var routes = _.reduce(routesDict, function (memo, data, route) {
                          memo[route] = {
                              get: function () {
                                  page.render(_.extend({}, data, getServerObject(this)));
                              }
                          };
                          return memo;
                      }, {});
  
                      routes['/api'] = {
                          '/terms': {
                              get: function () {
                                  var that = this;
  
                                  var id = (that.req.query.id || '').trim();
                                  var pageName = (that.req.query.pageName || '').trim();
                                  var data = {};
  
                                  if (id === 'widget-header') {
                                      data = {
                                          title: 'SPA Sushi'
                                      };
                                  } else if (id === 'widget-content') {
                                      data = {
                                          termGoBack: '<< Go back'
                                      };
                                  } else if (id === 'widget-footer') {
                                      data = {
                                          text: '&copy; 2013 Alexandr Marinenko'
                                      };
                                  } else if (id === 'widget-links') {
                                      data = {
                                          items: [
                                              {page: 'home', name: 'Home'},
                                              {page: 'about', name: 'About'},
                                              {page: 'contact', name: 'Contact'}
                                          ]
                                      };
                                  } else if (id === 'widget-info') {
                                      if (pageName === 'about') {
                                          data = {
                                              text: 'You\'re on <span class="highlight js-highlight">About</span> page.'
                                          };
                                      } else if (pageName === 'contact') {
                                          data = {
                                              text: 'You\'re on <span class="highlight js-highlight">Contact</span> page.'
                                          };
                                      }
                                  }
  
                                  that.res.set('Content-Type', 'application/json');
                                  that.res.json(200, data);
                              }
                          }
                      };
  
                      routing.router = new router.http.Router(routes);
  
                      data.server.use(function routerMiddleware(req, res, next) {
                          routing.router.dispatch(req, res, function (err) {
                              if (err) {
                                  page.render(_.extend({
                                      routeData: {
                                          pageName: 'not-found'
                                      }
                                  }, getServerObject(this)));
                              }
                          });
                      });
  
                      if (cb && typeof cb === 'function') {
                          cb(data);
                      }
                  }
              };
  
              if ('bus' in app) {
                  app.bus.on(app.namespace + '::' + moduleName + '::init', function (data, cb) {
                      routing.init(data, cb);
                  });
              }
  
              return routing;
          }
      };
  })(module);
  },{}],13:[function(require,module,exports){
  (function utilsInit(module) {
      'use strict';
  
      module.exports = {
          init: function (app, window, $, _, browser, undefined) {
  
              /* a little hack for a server side */
              if (!window) {
                  window = {};
              }
              if (!window.JSON && JSON) {
                  window.JSON = JSON;
              }
              if (!window.Math && Math) {
                  window.Math = Math;
              }
              if (!window.RegExp && RegExp) {
                  window.RegExp = RegExp;
              }
              /* hack ends */
  
              var utils = {
                  deepCopy: function (obj) {
                      return window.JSON.parse(window.JSON.stringify(obj) || 'null');
                  },
  
                  deepExtend: function (dest, source) {
                      if (!dest) {
                          return null;
                      }
  
                      if (!source) {
                          return dest;
                      }
  
                      if (typeof source === 'object') {
                          if (!source) {
                              dest = source;
                          } else {
                              for (var key in source) {
                                  var destProp = dest[key];
                                  var sourceProp = source[key];
                                  if (destProp && sourceProp && typeof sourceProp === 'object') {
                                      utils.deepExtend(destProp, sourceProp);
                                  } else {
                                      dest[key] = sourceProp;
                                  }
                              }
                          }
                      } else {
                          dest = source;
                      }
                      return dest;
                  },
  
                  removeProperty: function (obj, propName) {
                      if (obj[propName]) {
                          var result = _.extend({}, obj);
                          delete result[propName];
                          return result;
                      }
                      return obj;
                  },
  
                  simplifyObject: function (obj, goLevelDown) {
                      if (!obj) {
                          return null;
                      }
  
                      var result = {};
                      for (var prop in obj) {
                          if (typeof obj[prop] === 'object') {
                              if (goLevelDown) {
                                  result[prop] = utils.simplifyObject(obj[prop], false);
                              }
                          } else if (typeof obj[prop] !== 'function' && typeof obj[prop] !== 'unknown') {
                              result[prop] = obj[prop];
                          }
                      }
                      return result;
                  },
  
                  parseNumber: function (str) {
                      if (str) {
                          return +(str.match(/-{0,1}\d+(\.\d+)?/g) || [0])[0];
                      } else {
                          return 0;
                      }
                  },
  
                  generateGuid: function () {
                      var numberGroup = function () {
                          return (((1 + window.Math.random()) * 0x10000) | 0).toString(16).substring(1);
                      };
                      return (numberGroup() + numberGroup() + "-" + numberGroup() + "-" + numberGroup() + "-" +
                          numberGroup() + "-" + numberGroup() + numberGroup() + numberGroup());
                  },
  
                  isInputEmpty: function (input) {
                      input.removeClass('error');
                      if (input.val() === '') {
                          input.addClass('error');
                          return false;
                      }
                      return true;
                  },
  
                  isInputEmailValid: function (input) {
                      input.removeClass('error');
                      if (!utils.validateEmail(input.val())) {
                          input.addClass('error');
                          return false;
                      }
                      return true;
                  },
  
                  validateEmail: function (email) {
                      var regEx = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
                      return regEx.test(email);
                  },
  
                  loadScript: function (src, cb, id) {
                      /// <summary>
                      /// Loads script in async way and executes callback once it's loaded
                      /// </summary>
  
                      if (window && window.document) {
                          /* async isn't properly supported by IE8/9 */
                          var isAsync = !browser.ie8 && !browser.ie9;
  
                          var script = window.document.createElement('script');
                          script.src = src;
                          script.type = 'text/javascript';
  
                          if (id) {
                              script.setAttribute('id', id);
                          }
  
                          if (isAsync) {
                              script.async = 'true';
  
                              var callback = function () {
                                  var rs = this.readyState;
                                  if (rs && rs != 'complete' && rs != 'loaded') {
                                      return;
                                  }
                                  if (cb && typeof cb === 'function') {
                                      cb();
                                  }
                              };
  
                              if (script.addEventListener) {
                                  script.addEventListener('load', callback, false);
                              } else if (script.readyState) {
                                  script.onreadystatechange = callback;
                              }
                          }
  
                          var placeholder = window.document.getElementsByTagName('script')[0];
                          placeholder.parentNode.insertBefore(script, placeholder);
  
                          if (!isAsync) {
                              if (cb && typeof cb === 'function') {
                                  cb();
                              }
                          }
                      }
                  },
  
                  placeScript: function (code, cb, id) {
                      /// <summary>
                      /// Places script in async way and executes callback once it's loaded
                      /// </summary>
  
                      if (window && window.document) {
                          /* async isn't properly supported by IE8/9 */
                          var isAsync = !browser.ie8 && !browser.ie9;
  
                          var script = window.document.createElement('script');
                          script.innerHTML = code;
                          script.type = 'text/javascript';
  
                          if (id) {
                              script.setAttribute('id', id);
                          }
  
                          if (isAsync) {
                              script.async = 'true';
                              var callback = function () {
                                  var rs = this.readyState;
                                  if (rs && rs != 'complete' && rs != 'loaded') {
                                      return;
                                  }
                                  if (cb && typeof cb === 'function') {
                                      cb();
                                  }
                              };
  
                              if (script.addEventListener) {
                                  script.addEventListener('load', callback, false);
                              } else if (script.readyState) {
                                  script.onreadystatechange = callback;
                              }
                          }
  
                          var placeholder = window.document.getElementsByTagName('script')[0];
                          placeholder.parentNode.insertBefore(script, placeholder);
  
                          if (!isAsync) {
                              if (cb && typeof cb === 'function') {
                                  cb();
                              }
                          }
                      }
                  },
  
                  isScriptOnPage: function (src) {
                      if (window && window.document) {
                          return _.chain(window.document.getElementsByTagName('script'))
                              .map(function (s) { return s.getAttribute('src') || ''; })
                              .filter(function (s) { return s.indexOf(src) >= 0; })
                              .value().length > 0;
                      }
                      return false;
                  },
  
                  isRegExTrue: function (value, pattern) {
                      return new window.RegExp(pattern).test(value);
                  }
              };
  
              return utils;
          }
      };
  })(module);
  },{}],14:[function(require,module,exports){
  (function widgetContentConfigure(module) {
    'use strict';
  
    module.exports = {
      'controllers': [
        {
          name: 'widgetContentController',
          type: require('./js/controller.js').init,
          deps: ['app', 'window', '$', '_', 'ajax']
        },
        {
          name: 'widgetContentStructure',
          type: require('./js/structure.js').init,
          deps: []
        }
      ],
      'presenters': [
        {
          name: 'widgetContentPresenter',
          type: require('./js/presenter.js').init,
          deps: ['app', 'window', '$', '_', 'async', 'widgetContentStructure']
        }
      ],
      'wireups': [
        {
          name: 'widgetContentWireup',
          type: require('./js/wireup.js').init,
          deps: ['app', 'window', '$', '_', 'async', 'widgetContentStructure']
        }
      ]
    };
  })(module);
  
  },{"./js/controller.js":15,"./js/presenter.js":16,"./js/structure.js":17,"./js/wireup.js":18}],15:[function(require,module,exports){
  (function widgetContentControllerInit(module) {
      'use strict';
  
      var moduleName = 'widget-content';
  
      module.exports = {
          init: function (app, window, $, _, ajax, undefined) {
              var controller = {
                  get: function (data, cb) {
                      ajax.get({
                          url: '/api/terms',
                          data: data
                      }, function (err, response) {
                          if (cb && typeof cb === 'function') {
                              cb(err, response);
                          }
                      });
                  }
              };
  
              if (app.bus) {
                  app.bus.on(app.namespace + '::' + moduleName + '::get', function (data, cb) {
                      controller.get(data, cb);
                  });
              }
  
              return controller;
          }
      };
  })(module);
  },{}],16:[function(require,module,exports){
  (function widgetContentPresenterInit(module) {
      'use strict';
  
      var moduleName = 'widget-content';
  
      module.exports = {
          init: function (app, window, $, _, async, structure, undefined) {
              var presenter = {
                  render: function (data, cb) {
                      app.bus.emit(app.namespace + '::' + moduleName + '::get', data, function (err, response) {
                          var createAsyncCall = function (features) {
                              return _.reduce(features, function (memo, feature) {
                                  memo[feature.id] = function (cb) {
                                      app.bus.emit(app.namespace + '::' + feature.id + '::render', data, cb);
                                  };
                                  return memo;
                              }, {});
                          };
  
                          var asyncCallback = function (err, asyncData) {
                              var template = app.templates[moduleName + '/' + data.pageName];
                              var html = template ? template.render(_.extend(response, asyncData)) : '';
  
                              app.bus.emit(app.namespace + '::' + moduleName + '::loaded', html);
  
                              if (cb && typeof cb === 'function') {
                                  cb(null, html);
                              }
                          };
  
                          if (structure[data.pageName]) {
                              async.parallel(createAsyncCall(structure[data.pageName]), asyncCallback);
                          } else {
                              asyncCallback(null, {});
                          }
                      });
                  }
              };
  
              if (app.bus) {
                  app.bus.on(app.namespace + '::' + moduleName + '::render', function (data, cb) {
                      presenter.render(_.extend(data, {id: moduleName}), cb);
                  });
              }
  
              return presenter;
          }
      };
  })(module);
  },{}],17:[function(require,module,exports){
  (function widgetContentStructureInit(module) {
      'use strict';
  
      module.exports = {
          init: function (undefined) {
              return {
                  'home': [
                      {
                          id: 'widget-links',
                          container: '.links-container'
                      }
                  ],
                  'about': [
                      {
                          id: 'widget-info',
                          container: '.info-container'
                      }
                  ],
                  'contact': [
                      {
                          id: 'widget-info',
                          container: '.info-container'
                      },
                      {
                          id: 'widget-social',
                          container: '.social-container'
                      }
                  ]
              };
          }
      };
  })(module);
  },{}],18:[function(require,module,exports){
  (function widgetContentWireupInit(module) {
      'use strict';
  
      var moduleName = 'widget-content';
      var animationTimeout = 250;
  
      module.exports = {
          init: function (app, window, $, _, async, structure, undefined) {
              var wireup = function (data, cb) {
                  var createAsyncCall = function (features) {
                      return _.reduce(features, function (memo, feature) {
                          memo[feature.id] = function (cb) {
                              app.bus.emit(app.namespace + '::' + feature.id + '::wireup',
                                  _.extend({}, data, {container: data.container.find(feature.container)}),
                                  cb);
                          };
                          return memo;
                      }, {});
                  };
  
                  var asyncCallback = function (err, asyncData) {
                      if (cb && typeof cb === 'function') {
                          cb(null, data);
                      }
                  };
  
                  if (structure[data.pageName]) {
                      async.parallel(createAsyncCall(structure[data.pageName]), asyncCallback);
                  } else {
                      asyncCallback(null, data);
                  }
              };
  
              if (app.bus) {
                  app.bus.on(app.namespace + '::' + moduleName + '::wireup', function (data, cb) {
                      wireup(data, cb);
                  });
              }
  
              return wireup;
          }
      };
  })(module);
  },{}],19:[function(require,module,exports){
  (function widgetFooterConfigure(module) {
    'use strict';
  
    module.exports = {
      'controllers': [
        {
          name: 'widgetFooterController',
          type: require('./js/controller.js').init,
          deps: ['app', 'window', '$', '_', 'ajax']
        }
      ],
      'presenters': [
        {
          name: 'widgetFooterPresenter',
          type: require('./js/presenter.js').init,
          deps: ['app', 'window', '$', '_']
        }
      ],
      'wireups': [
        {
          name: 'widgetFooterWireup',
          type: require('./js/wireup.js').init,
          deps: ['app', 'window', '$', '_']
        }
      ]
    };
  })(module);
  
  },{"./js/controller.js":20,"./js/presenter.js":21,"./js/wireup.js":22}],20:[function(require,module,exports){
  (function widgetFooterControllerInit(module) {
      'use strict';
  
      var moduleName = 'widget-footer';
  
      module.exports = {
          init: function (app, window, $, _, ajax, undefined) {
              var controller = {
                  get: function (data, cb) {
                      ajax.get({
                          url: '/api/terms',
                          data: data
                      }, function (err, response) {
                          if (cb && typeof cb === 'function') {
                              cb(err, response);
                          }
                      });
                  }
              };
  
              if (app.bus) {
                  app.bus.on(app.namespace + '::' + moduleName + '::get', function (data, cb) {
                      controller.get(data, cb);
                  });
              }
  
              return controller;
          }
      };
  })(module);
  },{}],21:[function(require,module,exports){
  (function widgetFooterPresenterInit(module) {
      'use strict';
  
      var moduleName = 'widget-footer';
  
      module.exports = {
          init: function (app, window, $, _, undefined) {
              var presenter = {
                  render: function (data, cb) {
                      app.bus.emit(app.namespace + '::' + moduleName + '::get', data, function (err, response) {
                          var html = app.templates[moduleName + '/main'].render(response);
  
                          app.bus.emit(app.namespace + '::' + moduleName + '::loaded', html);
  
                          if (cb && typeof cb === 'function') {
                              cb(null, html);
                          }
                      });
                  }
              };
  
              if (app.bus) {
                  app.bus.on(app.namespace + '::' + moduleName + '::render', function (data, cb) {
                      presenter.render(_.extend(data, {id: moduleName}), cb);
                  });
              }
  
              return presenter;
          }
      };
  })(module);
  },{}],22:[function(require,module,exports){
  (function widgetFooterWireupInit(module) {
      'use strict';
  
      var moduleName = 'widget-footer';
      var animationTimeout = 250;
  
      module.exports = {
          init: function (app, window, $, _, undefined) {
              var wireup = function (data, cb) {
                  if (cb && typeof cb === 'function') {
                      cb(null, data);
                  }
              };
  
              if (app.bus) {
                  app.bus.on(app.namespace + '::' + moduleName + '::wireup', function (data, cb) {
                      wireup(data, cb);
                  });
              }
  
              return wireup;
          }
      };
  })(module);
  },{}],23:[function(require,module,exports){
  (function widgetHeaderConfigure(module) {
    'use strict';
  
    module.exports = {
      'controllers': [
        {
          name: 'widgetHeaderController',
          type: require('./js/controller.js').init,
          deps: ['app', 'window', '$', '_', 'ajax']
        }
      ],
      'presenters': [
        {
          name: 'widgetHeaderPresenter',
          type: require('./js/presenter.js').init,
          deps: ['app', 'window', '$', '_']
        }
      ],
      'wireups': [
        {
          name: 'widgetHeaderWireup',
          type: require('./js/wireup.js').init,
          deps: ['app', 'window', '$', '_']
        }
      ]
    };
  })(module);
  
  },{"./js/controller.js":24,"./js/presenter.js":25,"./js/wireup.js":26}],24:[function(require,module,exports){
  (function widgetHeaderControllerInit(module) {
      'use strict';
  
      var moduleName = 'widget-header';
  
      module.exports = {
          init: function (app, window, $, _, ajax, undefined) {
              var controller = {
                  get: function (data, cb) {
                      ajax.get({
                          url: '/api/terms',
                          data: data
                      }, function (err, response) {
                          if (cb && typeof cb === 'function') {
                              cb(err, response);
                          }
                      });
                  }
              };
  
              if (app.bus) {
                  app.bus.on(app.namespace + '::' + moduleName + '::get', function (data, cb) {
                      controller.get(data, cb);
                  });
              }
  
              return controller;
          }
      };
  })(module);
  },{}],25:[function(require,module,exports){
  (function widgetHeaderPresenterInit(module) {
      'use strict';
  
      var moduleName = 'widget-header';
  
      module.exports = {
          init: function (app, window, $, _, undefined) {
              var presenter = {
                  render: function (data, cb) {
                      app.bus.emit(app.namespace + '::' + moduleName + '::get', data, function (err, response) {
                          var html = app.templates[moduleName + '/main'].render(response);
  
                          app.bus.emit(app.namespace + '::' + moduleName + '::loaded', html);
  
                          if (cb && typeof cb === 'function') {
                              cb(null, html);
                          }
                      });
                  }
              };
  
              if (app.bus) {
                  app.bus.on(app.namespace + '::' + moduleName + '::render', function (data, cb) {
                      presenter.render(_.extend(data, {id: moduleName}), cb);
                  });
              }
  
              return presenter;
          }
      };
  })(module);
  },{}],26:[function(require,module,exports){
  (function widgetHeaderWireupInit(module) {
      'use strict';
  
      var moduleName = 'widget-header';
      var animationTimeout = 250;
  
      module.exports = {
          init: function (app, window, $, _, undefined) {
              var wireup = function (data, cb) {
                  if (cb && typeof cb === 'function') {
                      cb(null, data);
                  }
              };
  
              if (app.bus) {
                  app.bus.on(app.namespace + '::' + moduleName + '::wireup', function (data, cb) {
                      wireup(data, cb);
                  });
              }
  
              return wireup;
          }
      };
  })(module);
  },{}],27:[function(require,module,exports){
  (function widgetInfoConfigure(module) {
    'use strict';
  
    module.exports = {
      'controllers': [
        {
          name: 'widgetInfoController',
          type: require('./js/controller.js').init,
          deps: ['app', 'window', '$', '_', 'ajax']
        }
      ],
      'presenters': [
        {
          name: 'widgetInfoPresenter',
          type: require('./js/presenter.js').init,
          deps: ['app', 'window', '$', '_']
        }
      ],
      'wireups': [
        {
          name: 'widgetInfoWireup',
          type: require('./js/wireup.js').init,
          deps: ['app', 'window', '$', '_']
        }
      ]
    };
  })(module);
  
  },{"./js/controller.js":28,"./js/presenter.js":29,"./js/wireup.js":30}],28:[function(require,module,exports){
  (function widgetInfoControllerInit(module) {
      'use strict';
  
      var moduleName = 'widget-info';
  
      module.exports = {
          init: function (app, window, $, _, ajax, undefined) {
              var controller = {
                  get: function (data, cb) {
                      ajax.get({
                          url: '/api/terms',
                          data: data
                      }, function (err, response) {
                          if (cb && typeof cb === 'function') {
                              cb(err, response);
                          }
                      });
                  }
              };
  
              if (app.bus) {
                  app.bus.on(app.namespace + '::' + moduleName + '::get', function (data, cb) {
                      controller.get(data, cb);
                  });
              }
  
              return controller;
          }
      };
  })(module);
  },{}],29:[function(require,module,exports){
  (function widgetInfoPresenterInit(module) {
      'use strict';
  
      var moduleName = 'widget-info';
  
      module.exports = {
          init: function (app, window, $, _, undefined) {
              var presenter = {
                  render: function (data, cb) {
                      app.bus.emit(app.namespace + '::' + moduleName + '::get', {
                          id: data.id,
                          pageName: data.pageName
                      }, function (errGet, dataGet) {
                          var html = app.templates[moduleName + '/main'].render(_.extend({}, data, dataGet));
  
                          app.bus.emit(app.namespace + '::' + moduleName + '::loaded', html);
  
                          if (cb && typeof cb === 'function') {
                              cb(null, html);
                          }
                      });
                  }
              };
  
              if (app.bus) {
                  app.bus.on(app.namespace + '::' + moduleName + '::render', function (data, cb) {
                      presenter.render(_.extend(data, {id: moduleName}), cb);
                  });
              }
  
              return presenter;
          }
      };
  })(module);
  },{}],30:[function(require,module,exports){
  (function widgetInfoWireupInit(module) {
      'use strict';
  
      var moduleName = 'widget-info';
      var animationTimeout = 250;
  
      module.exports = {
          init: function (app, window, $, _, undefined) {
              var wireup = function (data, cb) {
                  var container = data.container;
  
                  container
                      .off('click.' + moduleName, '.js-highlight')
                      .on('click.' + moduleName, '.js-highlight', function (event) {
                          var span = $(event.currentTarget).toggleClass('clicked');
                          return true;
                      });
  
                  if (cb && typeof cb === 'function') {
                      cb(null, data);
                  }
              };
  
              if (app.bus) {
                  app.bus.on(app.namespace + '::' + moduleName + '::wireup', function (data, cb) {
                      wireup(data, cb);
                  });
              }
  
              return wireup;
          }
      };
  })(module);
  },{}],31:[function(require,module,exports){
  (function widgetLinksConfigure(module) {
    'use strict';
  
    module.exports = {
      'controllers': [
        {
          name: 'widgetLinksController',
          type: require('./js/controller.js').init,
          deps: ['app', 'window', '$', '_', 'ajax']
        }
      ],
      'presenters': [
        {
          name: 'widgetLinksPresenter',
          type: require('./js/presenter.js').init,
          deps: ['app', 'window', '$', '_']
        }
      ],
      'wireups': [
        {
          name: 'widgetLinksWireup',
          type: require('./js/wireup.js').init,
          deps: ['app', 'window', '$', '_']
        }
      ]
    };
  })(module);
  
  },{"./js/controller.js":32,"./js/presenter.js":33,"./js/wireup.js":34}],32:[function(require,module,exports){
  (function widgetLinksControllerInit(module) {
      'use strict';
  
      var moduleName = 'widget-links';
  
      module.exports = {
          init: function (app, window, $, _, ajax, undefined) {
              var controller = {
                  get: function (data, cb) {
                      ajax.get({
                          url: '/api/terms',
                          data: data
                      }, function (err, response) {
                          if (cb && typeof cb === 'function') {
                              cb(err, response);
                          }
                      });
                  }
              };
  
              if (app.bus) {
                  app.bus.on(app.namespace + '::' + moduleName + '::get', function (data, cb) {
                      controller.get(data, cb);
                  });
              }
  
              return controller;
          }
      };
  })(module);
  },{}],33:[function(require,module,exports){
  (function widgetLinksPresenterInit(module) {
      'use strict';
  
      var moduleName = 'widget-links';
  
      module.exports = {
          init: function (app, window, $, _, undefined) {
              var presenter = {
                  render: function (data, cb) {
                      app.bus.emit(app.namespace + '::' + moduleName + '::get', {id: data.id}, function (errGet, dataGet) {
                          var html = app.templates[moduleName + '/main'].render(_.extend({}, data, dataGet));
  
                          app.bus.emit(app.namespace + '::' + moduleName + '::loaded', html);
  
                          if (cb && typeof cb === 'function') {
                              cb(null, html);
                          }
                      });
                  }
              };
  
              if (app.bus) {
                  app.bus.on(app.namespace + '::' + moduleName + '::render', function (data, cb) {
                      presenter.render(_.extend(data, {id: moduleName}), cb);
                  });
              }
  
              return presenter;
          }
      };
  })(module);
  },{}],34:[function(require,module,exports){
  (function widgetLinksWireupInit(module) {
      'use strict';
  
      var moduleName = 'widget-links';
      var animationTimeout = 250;
  
      module.exports = {
          init: function (app, window, $, _, undefined) {
              var wireup = function (data, cb) {
                  var container = data.container;
  
                  if (cb && typeof cb === 'function') {
                      cb(null, data);
                  }
              };
  
              if (app.bus) {
                  app.bus.on(app.namespace + '::' + moduleName + '::wireup', function (data, cb) {
                      wireup(data, cb);
                  });
              }
  
              return wireup;
          }
      };
  })(module);
  },{}],35:[function(require,module,exports){
  (function widgetSocialConfigure(module) {
    'use strict';
  
    module.exports = {
      'controllers': [
        {
          name: 'widgetSocialController',
          type: require('./js/controller.js').init,
          deps: ['app', 'window', '$', '_', 'ajax']
        }
      ],
      'presenters': [
        {
          name: 'widgetSocialPresenter',
          type: require('./js/presenter.js').init,
          deps: ['app', 'window', '$', '_']
        }
      ],
      'wireups': [
        {
          name: 'widgetSocialWireup',
          type: require('./js/wireup.js').init,
          deps: ['app', 'window', '$', '_']
        }
      ]
    };
  })
  (module);
  
  },{"./js/controller.js":36,"./js/presenter.js":37,"./js/wireup.js":38}],36:[function(require,module,exports){
  (function widgetSocialControllerInit(module) {
      'use strict';
  
      var moduleName = 'widget-social';
  
      module.exports = {
          init: function (app, window, $, _, ajax, undefined) {
              var controller = {
                  get: function (data, cb) {
                      ajax.get({
                          url: '/api/terms',
                          data: data
                      }, function (err, response) {
                          if (cb && typeof cb === 'function') {
                              cb(err, response);
                          }
                      });
                  }
              };
  
              if (app.bus) {
                  app.bus.on(app.namespace + '::' + moduleName + '::get', function (data, cb) {
                      controller.get(data, cb);
                  });
              }
  
              return controller;
          }
      };
  })(module);
  },{}],37:[function(require,module,exports){
  (function widgetSocialPresenterInit(module) {
      'use strict';
  
      var moduleName = 'widget-social';
  
      module.exports = {
          init: function (app, window, $, _, undefined) {
              var presenter = {
                  render: function (data, cb) {
                      app.bus.emit(app.namespace + '::' + moduleName + '::get', {id: data.id}, function (errGet, dataGet) {
                          var html = app.templates[moduleName + '/main'].render(_.extend({}, data, dataGet));
  
                          app.bus.emit(app.namespace + '::' + moduleName + '::loaded', html);
  
                          if (cb && typeof cb === 'function') {
                              cb(null, html);
                          }
                      });
                  }
              };
  
              if (app.bus) {
                  app.bus.on(app.namespace + '::' + moduleName + '::render', function (data, cb) {
                      presenter.render(_.extend(data, {id: moduleName}), cb);
                  });
              }
  
              return presenter;
          }
      };
  })(module);
  },{}],38:[function(require,module,exports){
  (function widgetSocialWireupInit(module) {
      'use strict';
  
      var moduleName = 'widget-social';
      var animationTimeout = 250;
  
      module.exports = {
          init: function (app, window, $, _, undefined) {
              var wireup = function (data, cb) {
                  var container = data.container;
  
                  if (cb && typeof cb === 'function') {
                      cb(null, data);
                  }
              };
  
              if (app.bus) {
                  app.bus.on(app.namespace + '::' + moduleName + '::wireup', function (data, cb) {
                      wireup(data, cb);
                  });
              }
  
              return wireup;
          }
      };
  })(module);
  },{}],39:[function(require,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,require('_process'))
  },{"_process":54}],40:[function(require,module,exports){
  
  
  //
  // Generated on Fri Dec 27 2013 12:02:11 GMT-0500 (EST) by Nodejitsu, Inc (Using Codesurgeon).
  // Version 1.2.2
  //
  
  (function (exports) {
  
  /*
   * browser.js: Browser specific functionality for director.
   *
   * (C) 2011, Nodejitsu Inc.
   * MIT LICENSE
   *
   */
  
  if (!Array.prototype.filter) {
    Array.prototype.filter = function(filter, that) {
      var other = [], v;
      for (var i = 0, n = this.length; i < n; i++) {
        if (i in this && filter.call(that, v = this[i], i, this)) {
          other.push(v);
        }
      }
      return other;
    };
  }
  
  if (!Array.isArray){
    Array.isArray = function(obj) {
      return Object.prototype.toString.call(obj) === '[object Array]';
    };
  }
  
  var dloc = document.location;
  
  function dlocHashEmpty() {
    // Non-IE browsers return '' when the address bar shows '#'; Director's logic
    // assumes both mean empty.
    return dloc.hash === '' || dloc.hash === '#';
  }
  
  var listener = {
    mode: 'modern',
    hash: dloc.hash,
    history: false,
  
    check: function () {
      var h = dloc.hash;
      if (h != this.hash) {
        this.hash = h;
        this.onHashChanged();
      }
    },
  
    fire: function () {
      if (this.mode === 'modern') {
        this.history === true ? window.onpopstate() : window.onhashchange();
      }
      else {
        this.onHashChanged();
      }
    },
  
    init: function (fn, history) {
      var self = this;
      this.history = history;
  
      if (!Router.listeners) {
        Router.listeners = [];
      }
  
      function onchange(onChangeEvent) {
        for (var i = 0, l = Router.listeners.length; i < l; i++) {
          Router.listeners[i](onChangeEvent);
        }
      }
  
      //note IE8 is being counted as 'modern' because it has the hashchange event
      if ('onhashchange' in window && (document.documentMode === undefined
        || document.documentMode > 7)) {
        // At least for now HTML5 history is available for 'modern' browsers only
        if (this.history === true) {
          // There is an old bug in Chrome that causes onpopstate to fire even
          // upon initial page load. Since the handler is run manually in init(),
          // this would cause Chrome to run it twise. Currently the only
          // workaround seems to be to set the handler after the initial page load
          // http://code.google.com/p/chromium/issues/detail?id=63040
          setTimeout(function() {
            window.onpopstate = onchange;
          }, 500);
        }
        else {
          window.onhashchange = onchange;
        }
        this.mode = 'modern';
      }
      else {
        //
        // IE support, based on a concept by Erik Arvidson ...
        //
        var frame = document.createElement('iframe');
        frame.id = 'state-frame';
        frame.style.display = 'none';
        document.body.appendChild(frame);
        this.writeFrame('');
  
        if ('onpropertychange' in document && 'attachEvent' in document) {
          document.attachEvent('onpropertychange', function () {
            if (event.propertyName === 'location') {
              self.check();
            }
          });
        }
  
        window.setInterval(function () { self.check(); }, 50);
  
        this.onHashChanged = onchange;
        this.mode = 'legacy';
      }
  
      Router.listeners.push(fn);
  
      return this.mode;
    },
  
    destroy: function (fn) {
      if (!Router || !Router.listeners) {
        return;
      }
  
      var listeners = Router.listeners;
  
      for (var i = listeners.length - 1; i >= 0; i--) {
        if (listeners[i] === fn) {
          listeners.splice(i, 1);
        }
      }
    },
  
    setHash: function (s) {
      // Mozilla always adds an entry to the history
      if (this.mode === 'legacy') {
        this.writeFrame(s);
      }
  
      if (this.history === true) {
        window.history.pushState({}, document.title, s);
        // Fire an onpopstate event manually since pushing does not obviously
        // trigger the pop event.
        this.fire();
      } else {
        dloc.hash = (s[0] === '/') ? s : '/' + s;
      }
      return this;
    },
  
    writeFrame: function (s) {
      // IE support...
      var f = document.getElementById('state-frame');
      var d = f.contentDocument || f.contentWindow.document;
      d.open();
      d.write("<script>_hash = '" + s + "'; onload = parent.listener.syncHash;<script>");
      d.close();
    },
  
    syncHash: function () {
      // IE support...
      var s = this._hash;
      if (s != dloc.hash) {
        dloc.hash = s;
      }
      return this;
    },
  
    onHashChanged: function () {}
  };
  
  var Router = exports.Router = function (routes) {
    if (!(this instanceof Router)) return new Router(routes);
  
    this.params   = {};
    this.routes   = {};
    this.methods  = ['on', 'once', 'after', 'before'];
    this.scope    = [];
    this._methods = {};
  
    this._insert = this.insert;
    this.insert = this.insertEx;
  
    this.historySupport = (window.history != null ? window.history.pushState : null) != null
  
    this.configure();
    this.mount(routes || {});
  };
  
  Router.prototype.init = function (r) {
    var self = this;
    this.handler = function(onChangeEvent) {
      var newURL = onChangeEvent && onChangeEvent.newURL || window.location.hash;
      var url = self.history === true ? self.getPath() : newURL.replace(/.*#/, '');
      self.dispatch('on', url.charAt(0) === '/' ? url : '/' + url);
    };
  
    listener.init(this.handler, this.history);
  
    if (this.history === false) {
      if (dlocHashEmpty() && r) {
        dloc.hash = r;
      } else if (!dlocHashEmpty()) {
        self.dispatch('on', '/' + dloc.hash.replace(/^(#\/|#|\/)/, ''));
      }
    }
    else {
      var routeTo = dlocHashEmpty() && r ? r : !dlocHashEmpty() ? dloc.hash.replace(/^#/, '') : null;
      if (routeTo) {
        window.history.replaceState({}, document.title, routeTo);
      }
  
      // Router has been initialized, but due to the chrome bug it will not
      // yet actually route HTML5 history state changes. Thus, decide if should route.
      if (routeTo || this.run_in_init === true) {
        this.handler();
      }
    }
  
    return this;
  };
  
  Router.prototype.explode = function () {
    var v = this.history === true ? this.getPath() : dloc.hash;
    if (v.charAt(1) === '/') { v=v.slice(1) }
    return v.slice(1, v.length).split("/");
  };
  
  Router.prototype.setRoute = function (i, v, val) {
    var url = this.explode();
  
    if (typeof i === 'number' && typeof v === 'string') {
      url[i] = v;
    }
    else if (typeof val === 'string') {
      url.splice(i, v, s);
    }
    else {
      url = [i];
    }
  
    listener.setHash(url.join('/'));
    return url;
  };
  
  //
  // ### function insertEx(method, path, route, parent)
  // #### @method {string} Method to insert the specific `route`.
  // #### @path {Array} Parsed path to insert the `route` at.
  // #### @route {Array|function} Route handlers to insert.
  // #### @parent {Object} **Optional** Parent "routes" to insert into.
  // insert a callback that will only occur once per the matched route.
  //
  Router.prototype.insertEx = function(method, path, route, parent) {
    if (method === "once") {
      method = "on";
      route = function(route) {
        var once = false;
        return function() {
          if (once) return;
          once = true;
          return route.apply(this, arguments);
        };
      }(route);
    }
    return this._insert(method, path, route, parent);
  };
  
  Router.prototype.getRoute = function (v) {
    var ret = v;
  
    if (typeof v === "number") {
      ret = this.explode()[v];
    }
    else if (typeof v === "string"){
      var h = this.explode();
      ret = h.indexOf(v);
    }
    else {
      ret = this.explode();
    }
  
    return ret;
  };
  
  Router.prototype.destroy = function () {
    listener.destroy(this.handler);
    return this;
  };
  
  Router.prototype.getPath = function () {
    var path = window.location.pathname;
    if (path.substr(0, 1) !== '/') {
      path = '/' + path;
    }
    return path;
  };
  function _every(arr, iterator) {
    for (var i = 0; i < arr.length; i += 1) {
      if (iterator(arr[i], i, arr) === false) {
        return;
      }
    }
  }
  
  function _flatten(arr) {
    var flat = [];
    for (var i = 0, n = arr.length; i < n; i++) {
      flat = flat.concat(arr[i]);
    }
    return flat;
  }
  
  function _asyncEverySeries(arr, iterator, callback) {
    if (!arr.length) {
      return callback();
    }
    var completed = 0;
    (function iterate() {
      iterator(arr[completed], function(err) {
        if (err || err === false) {
          callback(err);
          callback = function() {};
        } else {
          completed += 1;
          if (completed === arr.length) {
            callback();
          } else {
            iterate();
          }
        }
      });
    })();
  }
  
  function paramifyString(str, params, mod) {
    mod = str;
    for (var param in params) {
      if (params.hasOwnProperty(param)) {
        mod = params[param](str);
        if (mod !== str) {
          break;
        }
      }
    }
    return mod === str ? "([._a-zA-Z0-9-]+)" : mod;
  }
  
  function regifyString(str, params) {
    var matches, last = 0, out = "";
    while (matches = str.substr(last).match(/[^\w\d\- %@&]*\*[^\w\d\- %@&]*/)) {
      last = matches.index + matches[0].length;
      matches[0] = matches[0].replace(/^\*/, "([_.()!\\ %@&a-zA-Z0-9-]+)");
      out += str.substr(0, matches.index) + matches[0];
    }
    str = out += str.substr(last);
    var captures = str.match(/:([^\/]+)/ig), capture, length;
    if (captures) {
      length = captures.length;
      for (var i = 0; i < length; i++) {
        capture = captures[i];
        if (capture.slice(0, 2) === "::") {
          str = capture.slice(1);
        } else {
          str = str.replace(capture, paramifyString(capture, params));
        }
      }
    }
    return str;
  }
  
  function terminator(routes, delimiter, start, stop) {
    var last = 0, left = 0, right = 0, start = (start || "(").toString(), stop = (stop || ")").toString(), i;
    for (i = 0; i < routes.length; i++) {
      var chunk = routes[i];
      if (chunk.indexOf(start, last) > chunk.indexOf(stop, last) || ~chunk.indexOf(start, last) && !~chunk.indexOf(stop, last) || !~chunk.indexOf(start, last) && ~chunk.indexOf(stop, last)) {
        left = chunk.indexOf(start, last);
        right = chunk.indexOf(stop, last);
        if (~left && !~right || !~left && ~right) {
          var tmp = routes.slice(0, (i || 1) + 1).join(delimiter);
          routes = [ tmp ].concat(routes.slice((i || 1) + 1));
        }
        last = (right > left ? right : left) + 1;
        i = 0;
      } else {
        last = 0;
      }
    }
    return routes;
  }
  
  Router.prototype.configure = function(options) {
    options = options || {};
    for (var i = 0; i < this.methods.length; i++) {
      this._methods[this.methods[i]] = true;
    }
    this.recurse = options.recurse || this.recurse || false;
    this.async = options.async || false;
    this.delimiter = options.delimiter || "/";
    this.strict = typeof options.strict === "undefined" ? true : options.strict;
    this.notfound = options.notfound;
    this.resource = options.resource;
    this.history = options.html5history && this.historySupport || false;
    this.run_in_init = this.history === true && options.run_handler_in_init !== false;
    this.every = {
      after: options.after || null,
      before: options.before || null,
      on: options.on || null
    };
    return this;
  };
  
  Router.prototype.param = function(token, matcher) {
    if (token[0] !== ":") {
      token = ":" + token;
    }
    var compiled = new RegExp(token, "g");
    this.params[token] = function(str) {
      return str.replace(compiled, matcher.source || matcher);
    };
  };
  
  Router.prototype.on = Router.prototype.route = function(method, path, route) {
    var self = this;
    if (!route && typeof path == "function") {
      route = path;
      path = method;
      method = "on";
    }
    if (Array.isArray(path)) {
      return path.forEach(function(p) {
        self.on(method, p, route);
      });
    }
    if (path.source) {
      path = path.source.replace(/\\\//ig, "/");
    }
    if (Array.isArray(method)) {
      return method.forEach(function(m) {
        self.on(m.toLowerCase(), path, route);
      });
    }
    path = path.split(new RegExp(this.delimiter));
    path = terminator(path, this.delimiter);
    this.insert(method, this.scope.concat(path), route);
  };
  
  Router.prototype.dispatch = function(method, path, callback) {
    var self = this, fns = this.traverse(method, path, this.routes, ""), invoked = this._invoked, after;
    this._invoked = true;
    if (!fns || fns.length === 0) {
      this.last = [];
      if (typeof this.notfound === "function") {
        this.invoke([ this.notfound ], {
          method: method,
          path: path
        }, callback);
      }
      return false;
    }
    if (this.recurse === "forward") {
      fns = fns.reverse();
    }
    function updateAndInvoke() {
      self.last = fns.after;
      self.invoke(self.runlist(fns), self, callback);
    }
    after = this.every && this.every.after ? [ this.every.after ].concat(this.last) : [ this.last ];
    if (after && after.length > 0 && invoked) {
      if (this.async) {
        this.invoke(after, this, updateAndInvoke);
      } else {
        this.invoke(after, this);
        updateAndInvoke();
      }
      return true;
    }
    updateAndInvoke();
    return true;
  };
  
  Router.prototype.invoke = function(fns, thisArg, callback) {
    var self = this;
    var apply;
    if (this.async) {
      apply = function(fn, next) {
        if (Array.isArray(fn)) {
          return _asyncEverySeries(fn, apply, next);
        } else if (typeof fn == "function") {
          fn.apply(thisArg, fns.captures.concat(next));
        }
      };
      _asyncEverySeries(fns, apply, function() {
        if (callback) {
          callback.apply(thisArg, arguments);
        }
      });
    } else {
      apply = function(fn) {
        if (Array.isArray(fn)) {
          return _every(fn, apply);
        } else if (typeof fn === "function") {
          return fn.apply(thisArg, fns.captures || []);
        } else if (typeof fn === "string" && self.resource) {
          self.resource[fn].apply(thisArg, fns.captures || []);
        }
      };
      _every(fns, apply);
    }
  };
  
  Router.prototype.traverse = function(method, path, routes, regexp, filter) {
    var fns = [], current, exact, match, next, that;
    function filterRoutes(routes) {
      if (!filter) {
        return routes;
      }
      function deepCopy(source) {
        var result = [];
        for (var i = 0; i < source.length; i++) {
          result[i] = Array.isArray(source[i]) ? deepCopy(source[i]) : source[i];
        }
        return result;
      }
      function applyFilter(fns) {
        for (var i = fns.length - 1; i >= 0; i--) {
          if (Array.isArray(fns[i])) {
            applyFilter(fns[i]);
            if (fns[i].length === 0) {
              fns.splice(i, 1);
            }
          } else {
            if (!filter(fns[i])) {
              fns.splice(i, 1);
            }
          }
        }
      }
      var newRoutes = deepCopy(routes);
      newRoutes.matched = routes.matched;
      newRoutes.captures = routes.captures;
      newRoutes.after = routes.after.filter(filter);
      applyFilter(newRoutes);
      return newRoutes;
    }
    if (path === this.delimiter && routes[method]) {
      next = [ [ routes.before, routes[method] ].filter(Boolean) ];
      next.after = [ routes.after ].filter(Boolean);
      next.matched = true;
      next.captures = [];
      return filterRoutes(next);
    }
    for (var r in routes) {
      if (routes.hasOwnProperty(r) && (!this._methods[r] || this._methods[r] && typeof routes[r] === "object" && !Array.isArray(routes[r]))) {
        current = exact = regexp + this.delimiter + r;
        if (!this.strict) {
          exact += "[" + this.delimiter + "]?";
        }
        match = path.match(new RegExp("^" + exact));
        if (!match) {
          continue;
        }
        if (match[0] && match[0] == path && routes[r][method]) {
          next = [ [ routes[r].before, routes[r][method] ].filter(Boolean) ];
          next.after = [ routes[r].after ].filter(Boolean);
          next.matched = true;
          next.captures = match.slice(1);
          if (this.recurse && routes === this.routes) {
            next.push([ routes.before, routes.on ].filter(Boolean));
            next.after = next.after.concat([ routes.after ].filter(Boolean));
          }
          return filterRoutes(next);
        }
        next = this.traverse(method, path, routes[r], current);
        if (next.matched) {
          if (next.length > 0) {
            fns = fns.concat(next);
          }
          if (this.recurse) {
            fns.push([ routes[r].before, routes[r].on ].filter(Boolean));
            next.after = next.after.concat([ routes[r].after ].filter(Boolean));
            if (routes === this.routes) {
              fns.push([ routes["before"], routes["on"] ].filter(Boolean));
              next.after = next.after.concat([ routes["after"] ].filter(Boolean));
            }
          }
          fns.matched = true;
          fns.captures = next.captures;
          fns.after = next.after;
          return filterRoutes(fns);
        }
      }
    }
    return false;
  };
  
  Router.prototype.insert = function(method, path, route, parent) {
    var methodType, parentType, isArray, nested, part;
    path = path.filter(function(p) {
      return p && p.length > 0;
    });
    parent = parent || this.routes;
    part = path.shift();
    if (/\:|\*/.test(part) && !/\\d|\\w/.test(part)) {
      part = regifyString(part, this.params);
    }
    if (path.length > 0) {
      parent[part] = parent[part] || {};
      return this.insert(method, path, route, parent[part]);
    }
    if (!part && !path.length && parent === this.routes) {
      methodType = typeof parent[method];
      switch (methodType) {
       case "function":
        parent[method] = [ parent[method], route ];
        return;
       case "object":
        parent[method].push(route);
        return;
       case "undefined":
        parent[method] = route;
        return;
      }
      return;
    }
    parentType = typeof parent[part];
    isArray = Array.isArray(parent[part]);
    if (parent[part] && !isArray && parentType == "object") {
      methodType = typeof parent[part][method];
      switch (methodType) {
       case "function":
        parent[part][method] = [ parent[part][method], route ];
        return;
       case "object":
        parent[part][method].push(route);
        return;
       case "undefined":
        parent[part][method] = route;
        return;
      }
    } else if (parentType == "undefined") {
      nested = {};
      nested[method] = route;
      parent[part] = nested;
      return;
    }
    throw new Error("Invalid route context: " + parentType);
  };
  
  
  
  Router.prototype.extend = function(methods) {
    var self = this, len = methods.length, i;
    function extend(method) {
      self._methods[method] = true;
      self[method] = function() {
        var extra = arguments.length === 1 ? [ method, "" ] : [ method ];
        self.on.apply(self, extra.concat(Array.prototype.slice.call(arguments)));
      };
    }
    for (i = 0; i < len; i++) {
      extend(methods[i]);
    }
  };
  
  Router.prototype.runlist = function(fns) {
    var runlist = this.every && this.every.before ? [ this.every.before ].concat(_flatten(fns)) : _flatten(fns);
    if (this.every && this.every.on) {
      runlist.push(this.every.on);
    }
    runlist.captures = fns.captures;
    runlist.source = fns.source;
    return runlist;
  };
  
  Router.prototype.mount = function(routes, path) {
    if (!routes || typeof routes !== "object" || Array.isArray(routes)) {
      return;
    }
    var self = this;
    path = path || [];
    if (!Array.isArray(path)) {
      path = path.split(self.delimiter);
    }
    function insertOrMount(route, local) {
      var rename = route, parts = route.split(self.delimiter), routeType = typeof routes[route], isRoute = parts[0] === "" || !self._methods[parts[0]], event = isRoute ? "on" : rename;
      if (isRoute) {
        rename = rename.slice((rename.match(new RegExp("^" + self.delimiter)) || [ "" ])[0].length);
        parts.shift();
      }
      if (isRoute && routeType === "object" && !Array.isArray(routes[route])) {
        local = local.concat(parts);
        self.mount(routes[route], local);
        return;
      }
      if (isRoute) {
        local = local.concat(rename.split(self.delimiter));
        local = terminator(local, self.delimiter);
      }
      self.insert(event, local, routes[route]);
    }
    for (var route in routes) {
      if (routes.hasOwnProperty(route)) {
        insertOrMount(route, path.slice(0));
      }
    }
  };
  
  
  
  }(typeof exports === "object" ? exports : window));
  },{}],41:[function(require,module,exports){
  /*!
   * EventEmitter2
   * https://github.com/hij1nx/EventEmitter2
   *
   * Copyright (c) 2013 hij1nx
   * Licensed under the MIT license.
   */
  ;!function(undefined) {
  
    var isArray = Array.isArray ? Array.isArray : function _isArray(obj) {
      return Object.prototype.toString.call(obj) === "[object Array]";
    };
    var defaultMaxListeners = 10;
  
    function init() {
      this._events = {};
      if (this._conf) {
        configure.call(this, this._conf);
      }
    }
  
    function configure(conf) {
      if (conf) {
  
        this._conf = conf;
  
        conf.delimiter && (this.delimiter = conf.delimiter);
        conf.maxListeners && (this._events.maxListeners = conf.maxListeners);
        conf.wildcard && (this.wildcard = conf.wildcard);
        conf.newListener && (this.newListener = conf.newListener);
  
        if (this.wildcard) {
          this.listenerTree = {};
        }
      }
    }
  
    function EventEmitter(conf) {
      this._events = {};
      this.newListener = false;
      configure.call(this, conf);
    }
  
    //
    // Attention, function return type now is array, always !
    // It has zero elements if no any matches found and one or more
    // elements (leafs) if there are matches
    //
    function searchListenerTree(handlers, type, tree, i) {
      if (!tree) {
        return [];
      }
      var listeners=[], leaf, len, branch, xTree, xxTree, isolatedBranch, endReached,
          typeLength = type.length, currentType = type[i], nextType = type[i+1];
      if (i === typeLength && tree._listeners) {
        //
        // If at the end of the event(s) list and the tree has listeners
        // invoke those listeners.
        //
        if (typeof tree._listeners === 'function') {
          handlers && handlers.push(tree._listeners);
          return [tree];
        } else {
          for (leaf = 0, len = tree._listeners.length; leaf < len; leaf++) {
            handlers && handlers.push(tree._listeners[leaf]);
          }
          return [tree];
        }
      }
  
      if ((currentType === '*' || currentType === '**') || tree[currentType]) {
        //
        // If the event emitted is '*' at this part
        // or there is a concrete match at this patch
        //
        if (currentType === '*') {
          for (branch in tree) {
            if (branch !== '_listeners' && tree.hasOwnProperty(branch)) {
              listeners = listeners.concat(searchListenerTree(handlers, type, tree[branch], i+1));
            }
          }
          return listeners;
        } else if(currentType === '**') {
          endReached = (i+1 === typeLength || (i+2 === typeLength && nextType === '*'));
          if(endReached && tree._listeners) {
            // The next element has a _listeners, add it to the handlers.
            listeners = listeners.concat(searchListenerTree(handlers, type, tree, typeLength));
          }
  
          for (branch in tree) {
            if (branch !== '_listeners' && tree.hasOwnProperty(branch)) {
              if(branch === '*' || branch === '**') {
                if(tree[branch]._listeners && !endReached) {
                  listeners = listeners.concat(searchListenerTree(handlers, type, tree[branch], typeLength));
                }
                listeners = listeners.concat(searchListenerTree(handlers, type, tree[branch], i));
              } else if(branch === nextType) {
                listeners = listeners.concat(searchListenerTree(handlers, type, tree[branch], i+2));
              } else {
                // No match on this one, shift into the tree but not in the type array.
                listeners = listeners.concat(searchListenerTree(handlers, type, tree[branch], i));
              }
            }
          }
          return listeners;
        }
  
        listeners = listeners.concat(searchListenerTree(handlers, type, tree[currentType], i+1));
      }
  
      xTree = tree['*'];
      if (xTree) {
        //
        // If the listener tree will allow any match for this part,
        // then recursively explore all branches of the tree
        //
        searchListenerTree(handlers, type, xTree, i+1);
      }
  
      xxTree = tree['**'];
      if(xxTree) {
        if(i < typeLength) {
          if(xxTree._listeners) {
            // If we have a listener on a '**', it will catch all, so add its handler.
            searchListenerTree(handlers, type, xxTree, typeLength);
          }
  
          // Build arrays of matching next branches and others.
          for(branch in xxTree) {
            if(branch !== '_listeners' && xxTree.hasOwnProperty(branch)) {
              if(branch === nextType) {
                // We know the next element will match, so jump twice.
                searchListenerTree(handlers, type, xxTree[branch], i+2);
              } else if(branch === currentType) {
                // Current node matches, move into the tree.
                searchListenerTree(handlers, type, xxTree[branch], i+1);
              } else {
                isolatedBranch = {};
                isolatedBranch[branch] = xxTree[branch];
                searchListenerTree(handlers, type, { '**': isolatedBranch }, i+1);
              }
            }
          }
        } else if(xxTree._listeners) {
          // We have reached the end and still on a '**'
          searchListenerTree(handlers, type, xxTree, typeLength);
        } else if(xxTree['*'] && xxTree['*']._listeners) {
          searchListenerTree(handlers, type, xxTree['*'], typeLength);
        }
      }
  
      return listeners;
    }
  
    function growListenerTree(type, listener) {
  
      type = typeof type === 'string' ? type.split(this.delimiter) : type.slice();
  
      //
      // Looks for two consecutive '**', if so, don't add the event at all.
      //
      for(var i = 0, len = type.length; i+1 < len; i++) {
        if(type[i] === '**' && type[i+1] === '**') {
          return;
        }
      }
  
      var tree = this.listenerTree;
      var name = type.shift();
  
      while (name) {
  
        if (!tree[name]) {
          tree[name] = {};
        }
  
        tree = tree[name];
  
        if (type.length === 0) {
  
          if (!tree._listeners) {
            tree._listeners = listener;
          }
          else if(typeof tree._listeners === 'function') {
            tree._listeners = [tree._listeners, listener];
          }
          else if (isArray(tree._listeners)) {
  
            tree._listeners.push(listener);
  
            if (!tree._listeners.warned) {
  
              var m = defaultMaxListeners;
  
              if (typeof this._events.maxListeners !== 'undefined') {
                m = this._events.maxListeners;
              }
  
              if (m > 0 && tree._listeners.length > m) {
  
                tree._listeners.warned = true;
                console.error('(node) warning: possible EventEmitter memory ' +
                              'leak detected. %d listeners added. ' +
                              'Use emitter.setMaxListeners() to increase limit.',
                              tree._listeners.length);
                console.trace();
              }
            }
          }
          return true;
        }
        name = type.shift();
      }
      return true;
    }
  
    // By default EventEmitters will print a warning if more than
    // 10 listeners are added to it. This is a useful default which
    // helps finding memory leaks.
    //
    // Obviously not all Emitters should be limited to 10. This function allows
    // that to be increased. Set to zero for unlimited.
  
    EventEmitter.prototype.delimiter = '.';
  
    EventEmitter.prototype.setMaxListeners = function(n) {
      this._events || init.call(this);
      this._events.maxListeners = n;
      if (!this._conf) this._conf = {};
      this._conf.maxListeners = n;
    };
  
    EventEmitter.prototype.event = '';
  
    EventEmitter.prototype.once = function(event, fn) {
      this.many(event, 1, fn);
      return this;
    };
  
    EventEmitter.prototype.many = function(event, ttl, fn) {
      var self = this;
  
      if (typeof fn !== 'function') {
        throw new Error('many only accepts instances of Function');
      }
  
      function listener() {
        if (--ttl === 0) {
          self.off(event, listener);
        }
        fn.apply(this, arguments);
      }
  
      listener._origin = fn;
  
      this.on(event, listener);
  
      return self;
    };
  
    EventEmitter.prototype.emit = function() {
  
      this._events || init.call(this);
  
      var type = arguments[0];
  
      if (type === 'newListener' && !this.newListener) {
        if (!this._events.newListener) { return false; }
      }
  
      // Loop through the *_all* functions and invoke them.
      if (this._all) {
        var l = arguments.length;
        var args = new Array(l - 1);
        for (var i = 1; i < l; i++) args[i - 1] = arguments[i];
        for (i = 0, l = this._all.length; i < l; i++) {
          this.event = type;
          this._all[i].apply(this, args);
        }
      }
  
      // If there is no 'error' event listener then throw.
      if (type === 'error') {
  
        if (!this._all &&
          !this._events.error &&
          !(this.wildcard && this.listenerTree.error)) {
  
          if (arguments[1] instanceof Error) {
            throw arguments[1]; // Unhandled 'error' event
          } else {
            throw new Error("Uncaught, unspecified 'error' event.");
          }
          return false;
        }
      }
  
      var handler;
  
      if(this.wildcard) {
        handler = [];
        var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice();
        searchListenerTree.call(this, handler, ns, this.listenerTree, 0);
      }
      else {
        handler = this._events[type];
      }
  
      if (typeof handler === 'function') {
        this.event = type;
        if (arguments.length === 1) {
          handler.call(this);
        }
        else if (arguments.length > 1)
          switch (arguments.length) {
            case 2:
              handler.call(this, arguments[1]);
              break;
            case 3:
              handler.call(this, arguments[1], arguments[2]);
              break;
            // slower
            default:
              var l = arguments.length;
              var args = new Array(l - 1);
              for (var i = 1; i < l; i++) args[i - 1] = arguments[i];
              handler.apply(this, args);
          }
        return true;
      }
      else if (handler) {
        var l = arguments.length;
        var args = new Array(l - 1);
        for (var i = 1; i < l; i++) args[i - 1] = arguments[i];
  
        var listeners = handler.slice();
        for (var i = 0, l = listeners.length; i < l; i++) {
          this.event = type;
          listeners[i].apply(this, args);
        }
        return (listeners.length > 0) || !!this._all;
      }
      else {
        return !!this._all;
      }
  
    };
  
    EventEmitter.prototype.on = function(type, listener) {
  
      if (typeof type === 'function') {
        this.onAny(type);
        return this;
      }
  
      if (typeof listener !== 'function') {
        throw new Error('on only accepts instances of Function');
      }
      this._events || init.call(this);
  
      // To avoid recursion in the case that type == "newListeners"! Before
      // adding it to the listeners, first emit "newListeners".
      this.emit('newListener', type, listener);
  
      if(this.wildcard) {
        growListenerTree.call(this, type, listener);
        return this;
      }
  
      if (!this._events[type]) {
        // Optimize the case of one listener. Don't need the extra array object.
        this._events[type] = listener;
      }
      else if(typeof this._events[type] === 'function') {
        // Adding the second element, need to change to array.
        this._events[type] = [this._events[type], listener];
      }
      else if (isArray(this._events[type])) {
        // If we've already got an array, just append.
        this._events[type].push(listener);
  
        // Check for listener leak
        if (!this._events[type].warned) {
  
          var m = defaultMaxListeners;
  
          if (typeof this._events.maxListeners !== 'undefined') {
            m = this._events.maxListeners;
          }
  
          if (m > 0 && this._events[type].length > m) {
  
            this._events[type].warned = true;
            console.error('(node) warning: possible EventEmitter memory ' +
                          'leak detected. %d listeners added. ' +
                          'Use emitter.setMaxListeners() to increase limit.',
                          this._events[type].length);
            console.trace();
          }
        }
      }
      return this;
    };
  
    EventEmitter.prototype.onAny = function(fn) {
  
      if (typeof fn !== 'function') {
        throw new Error('onAny only accepts instances of Function');
      }
  
      if(!this._all) {
        this._all = [];
      }
  
      // Add the function to the event listener collection.
      this._all.push(fn);
      return this;
    };
  
    EventEmitter.prototype.addListener = EventEmitter.prototype.on;
  
    EventEmitter.prototype.off = function(type, listener) {
      if (typeof listener !== 'function') {
        throw new Error('removeListener only takes instances of Function');
      }
  
      var handlers,leafs=[];
  
      if(this.wildcard) {
        var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice();
        leafs = searchListenerTree.call(this, null, ns, this.listenerTree, 0);
      }
      else {
        // does not use listeners(), so no side effect of creating _events[type]
        if (!this._events[type]) return this;
        handlers = this._events[type];
        leafs.push({_listeners:handlers});
      }
  
      for (var iLeaf=0; iLeaf<leafs.length; iLeaf++) {
        var leaf = leafs[iLeaf];
        handlers = leaf._listeners;
        if (isArray(handlers)) {
  
          var position = -1;
  
          for (var i = 0, length = handlers.length; i < length; i++) {
            if (handlers[i] === listener ||
              (handlers[i].listener && handlers[i].listener === listener) ||
              (handlers[i]._origin && handlers[i]._origin === listener)) {
              position = i;
              break;
            }
          }
  
          if (position < 0) {
            continue;
          }
  
          if(this.wildcard) {
            leaf._listeners.splice(position, 1);
          }
          else {
            this._events[type].splice(position, 1);
          }
  
          if (handlers.length === 0) {
            if(this.wildcard) {
              delete leaf._listeners;
            }
            else {
              delete this._events[type];
            }
          }
          return this;
        }
        else if (handlers === listener ||
          (handlers.listener && handlers.listener === listener) ||
          (handlers._origin && handlers._origin === listener)) {
          if(this.wildcard) {
            delete leaf._listeners;
          }
          else {
            delete this._events[type];
          }
        }
      }
  
      return this;
    };
  
    EventEmitter.prototype.offAny = function(fn) {
      var i = 0, l = 0, fns;
      if (fn && this._all && this._all.length > 0) {
        fns = this._all;
        for(i = 0, l = fns.length; i < l; i++) {
          if(fn === fns[i]) {
            fns.splice(i, 1);
            return this;
          }
        }
      } else {
        this._all = [];
      }
      return this;
    };
  
    EventEmitter.prototype.removeListener = EventEmitter.prototype.off;
  
    EventEmitter.prototype.removeAllListeners = function(type) {
      if (arguments.length === 0) {
        !this._events || init.call(this);
        return this;
      }
  
      if(this.wildcard) {
        var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice();
        var leafs = searchListenerTree.call(this, null, ns, this.listenerTree, 0);
  
        for (var iLeaf=0; iLeaf<leafs.length; iLeaf++) {
          var leaf = leafs[iLeaf];
          leaf._listeners = null;
        }
      }
      else {
        if (!this._events[type]) return this;
        this._events[type] = null;
      }
      return this;
    };
  
    EventEmitter.prototype.listeners = function(type) {
      if(this.wildcard) {
        var handlers = [];
        var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice();
        searchListenerTree.call(this, handlers, ns, this.listenerTree, 0);
        return handlers;
      }
  
      this._events || init.call(this);
  
      if (!this._events[type]) this._events[type] = [];
      if (!isArray(this._events[type])) {
        this._events[type] = [this._events[type]];
      }
      return this._events[type];
    };
  
    EventEmitter.prototype.listenersAny = function() {
  
      if(this._all) {
        return this._all;
      }
      else {
        return [];
      }
  
    };
  
    if (typeof define === 'function' && define.amd) {
       // AMD. Register as an anonymous module.
      define(function() {
        return EventEmitter;
      });
    } else if (typeof exports === 'object') {
      // CommonJS
      exports.EventEmitter2 = EventEmitter;
    }
    else {
      // Browser global.
      window.EventEmitter2 = EventEmitter;
    }
  }();
  
  },{}],42:[function(require,module,exports){
  /*!
   * The buffer module from node.js, for the browser.
   *
   * @author   Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
   * @license  MIT
   */
  
  var base64 = require('base64-js')
  var ieee754 = require('ieee754')
  var isArray = require('is-array')
  
  exports.Buffer = Buffer
  exports.SlowBuffer = SlowBuffer
  exports.INSPECT_MAX_BYTES = 50
  Buffer.poolSize = 8192 // not used by this implementation
  
  var kMaxLength = 0x3fffffff
  var rootParent = {}
  
  /**
   * If `Buffer.TYPED_ARRAY_SUPPORT`:
   *   === true    Use Uint8Array implementation (fastest)
   *   === false   Use Object implementation (most compatible, even IE6)
   *
   * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+,
   * Opera 11.6+, iOS 4.2+.
   *
   * Note:
   *
   * - Implementation must support adding new properties to `Uint8Array` instances.
   *   Firefox 4-29 lacked support, fixed in Firefox 30+.
   *   See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438.
   *
   *  - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function.
   *
   *  - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of
   *    incorrect length in some situations.
   *
   * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they will
   * get the Object implementation, which is slower but will work correctly.
   */
  Buffer.TYPED_ARRAY_SUPPORT = (function () {
    try {
      var buf = new ArrayBuffer(0)
      var arr = new Uint8Array(buf)
      arr.foo = function () { return 42 }
      return 42 === arr.foo() && // typed array instances can be augmented
          typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray`
          new Uint8Array(1).subarray(1, 1).byteLength === 0 // ie10 has broken `subarray`
    } catch (e) {
      return false
    }
  })()
  
  /**
   * Class: Buffer
   * =============
   *
   * The Buffer constructor returns instances of `Uint8Array` that are augmented
   * with function properties for all the node `Buffer` API functions. We use
   * `Uint8Array` so that square bracket notation works as expected -- it returns
   * a single octet.
   *
   * By augmenting the instances, we can avoid modifying the `Uint8Array`
   * prototype.
   */
  function Buffer (subject, encoding, noZero) {
    if (!(this instanceof Buffer))
      return new Buffer(subject, encoding, noZero)
  
    var type = typeof subject
  
    // Find the length
    var length
    if (type === 'number')
      length = subject > 0 ? subject >>> 0 : 0
    else if (type === 'string') {
      length = Buffer.byteLength(subject, encoding)
    } else if (type === 'object' && subject !== null) { // assume object is array-like
      if (subject.type === 'Buffer' && isArray(subject.data))
        subject = subject.data
      length = +subject.length > 0 ? Math.floor(+subject.length) : 0
    } else
      throw new TypeError('must start with number, buffer, array or string')
  
    if (length > kMaxLength)
      throw new RangeError('Attempt to allocate Buffer larger than maximum ' +
        'size: 0x' + kMaxLength.toString(16) + ' bytes')
  
    var buf
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      // Preferred: Return an augmented `Uint8Array` instance for best performance
      buf = Buffer._augment(new Uint8Array(length))
    } else {
      // Fallback: Return THIS instance of Buffer (created by `new`)
      buf = this
      buf.length = length
      buf._isBuffer = true
    }
  
    var i
    if (Buffer.TYPED_ARRAY_SUPPORT && typeof subject.byteLength === 'number') {
      // Speed optimization -- use set if we're copying from a typed array
      buf._set(subject)
    } else if (isArrayish(subject)) {
      // Treat array-ish objects as a byte array
      if (Buffer.isBuffer(subject)) {
        for (i = 0; i < length; i++)
          buf[i] = subject.readUInt8(i)
      } else {
        for (i = 0; i < length; i++)
          buf[i] = ((subject[i] % 256) + 256) % 256
      }
    } else if (type === 'string') {
      buf.write(subject, 0, encoding)
    } else if (type === 'number' && !Buffer.TYPED_ARRAY_SUPPORT && !noZero) {
      for (i = 0; i < length; i++) {
        buf[i] = 0
      }
    }
  
    if (length > 0 && length <= Buffer.poolSize)
      buf.parent = rootParent
  
    return buf
  }
  
  function SlowBuffer(subject, encoding, noZero) {
    if (!(this instanceof SlowBuffer))
      return new SlowBuffer(subject, encoding, noZero)
  
    var buf = new Buffer(subject, encoding, noZero)
    delete buf.parent
    return buf
  }
  
  Buffer.isBuffer = function (b) {
    return !!(b != null && b._isBuffer)
  }
  
  Buffer.compare = function (a, b) {
    if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b))
      throw new TypeError('Arguments must be Buffers')
  
    var x = a.length
    var y = b.length
    for (var i = 0, len = Math.min(x, y); i < len && a[i] === b[i]; i++) {}
    if (i !== len) {
      x = a[i]
      y = b[i]
    }
    if (x < y) return -1
    if (y < x) return 1
    return 0
  }
  
  Buffer.isEncoding = function (encoding) {
    switch (String(encoding).toLowerCase()) {
      case 'hex':
      case 'utf8':
      case 'utf-8':
      case 'ascii':
      case 'binary':
      case 'base64':
      case 'raw':
      case 'ucs2':
      case 'ucs-2':
      case 'utf16le':
      case 'utf-16le':
        return true
      default:
        return false
    }
  }
  
  Buffer.concat = function (list, totalLength) {
    if (!isArray(list)) throw new TypeError('Usage: Buffer.concat(list[, length])')
  
    if (list.length === 0) {
      return new Buffer(0)
    } else if (list.length === 1) {
      return list[0]
    }
  
    var i
    if (totalLength === undefined) {
      totalLength = 0
      for (i = 0; i < list.length; i++) {
        totalLength += list[i].length
      }
    }
  
    var buf = new Buffer(totalLength)
    var pos = 0
    for (i = 0; i < list.length; i++) {
      var item = list[i]
      item.copy(buf, pos)
      pos += item.length
    }
    return buf
  }
  
  Buffer.byteLength = function (str, encoding) {
    var ret
    str = str + ''
    switch (encoding || 'utf8') {
      case 'ascii':
      case 'binary':
      case 'raw':
        ret = str.length
        break
      case 'ucs2':
      case 'ucs-2':
      case 'utf16le':
      case 'utf-16le':
        ret = str.length * 2
        break
      case 'hex':
        ret = str.length >>> 1
        break
      case 'utf8':
      case 'utf-8':
        ret = utf8ToBytes(str).length
        break
      case 'base64':
        ret = base64ToBytes(str).length
        break
      default:
        ret = str.length
    }
    return ret
  }
  
  // pre-set for values that may exist in the future
  Buffer.prototype.length = undefined
  Buffer.prototype.parent = undefined
  
  // toString(encoding, start=0, end=buffer.length)
  Buffer.prototype.toString = function (encoding, start, end) {
    var loweredCase = false
  
    start = start >>> 0
    end = end === undefined || end === Infinity ? this.length : end >>> 0
  
    if (!encoding) encoding = 'utf8'
    if (start < 0) start = 0
    if (end > this.length) end = this.length
    if (end <= start) return ''
  
    while (true) {
      switch (encoding) {
        case 'hex':
          return hexSlice(this, start, end)
  
        case 'utf8':
        case 'utf-8':
          return utf8Slice(this, start, end)
  
        case 'ascii':
          return asciiSlice(this, start, end)
  
        case 'binary':
          return binarySlice(this, start, end)
  
        case 'base64':
          return base64Slice(this, start, end)
  
        case 'ucs2':
        case 'ucs-2':
        case 'utf16le':
        case 'utf-16le':
          return utf16leSlice(this, start, end)
  
        default:
          if (loweredCase)
            throw new TypeError('Unknown encoding: ' + encoding)
          encoding = (encoding + '').toLowerCase()
          loweredCase = true
      }
    }
  }
  
  Buffer.prototype.equals = function (b) {
    if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
    return Buffer.compare(this, b) === 0
  }
  
  Buffer.prototype.inspect = function () {
    var str = ''
    var max = exports.INSPECT_MAX_BYTES
    if (this.length > 0) {
      str = this.toString('hex', 0, max).match(/.{2}/g).join(' ')
      if (this.length > max)
        str += ' ... '
    }
    return '<Buffer ' + str + '>'
  }
  
  Buffer.prototype.compare = function (b) {
    if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
    return Buffer.compare(this, b)
  }
  
  // `get` will be removed in Node 0.13+
  Buffer.prototype.get = function (offset) {
    console.log('.get() is deprecated. Access using array indexes instead.')
    return this.readUInt8(offset)
  }
  
  // `set` will be removed in Node 0.13+
  Buffer.prototype.set = function (v, offset) {
    console.log('.set() is deprecated. Access using array indexes instead.')
    return this.writeUInt8(v, offset)
  }
  
  function hexWrite (buf, string, offset, length) {
    offset = Number(offset) || 0
    var remaining = buf.length - offset
    if (!length) {
      length = remaining
    } else {
      length = Number(length)
      if (length > remaining) {
        length = remaining
      }
    }
  
    // must be an even number of digits
    var strLen = string.length
    if (strLen % 2 !== 0) throw new Error('Invalid hex string')
  
    if (length > strLen / 2) {
      length = strLen / 2
    }
    for (var i = 0; i < length; i++) {
      var byte = parseInt(string.substr(i * 2, 2), 16)
      if (isNaN(byte)) throw new Error('Invalid hex string')
      buf[offset + i] = byte
    }
    return i
  }
  
  function utf8Write (buf, string, offset, length) {
    var charsWritten = blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length)
    return charsWritten
  }
  
  function asciiWrite (buf, string, offset, length) {
    var charsWritten = blitBuffer(asciiToBytes(string), buf, offset, length)
    return charsWritten
  }
  
  function binaryWrite (buf, string, offset, length) {
    return asciiWrite(buf, string, offset, length)
  }
  
  function base64Write (buf, string, offset, length) {
    var charsWritten = blitBuffer(base64ToBytes(string), buf, offset, length)
    return charsWritten
  }
  
  function utf16leWrite (buf, string, offset, length) {
    var charsWritten = blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length, 2)
    return charsWritten
  }
  
  Buffer.prototype.write = function (string, offset, length, encoding) {
    // Support both (string, offset, length, encoding)
    // and the legacy (string, encoding, offset, length)
    if (isFinite(offset)) {
      if (!isFinite(length)) {
        encoding = length
        length = undefined
      }
    } else {  // legacy
      var swap = encoding
      encoding = offset
      offset = length
      length = swap
    }
  
    offset = Number(offset) || 0
  
    if (length < 0 || offset < 0 || offset > this.length)
      throw new RangeError('attempt to write outside buffer bounds');
  
    var remaining = this.length - offset
    if (!length) {
      length = remaining
    } else {
      length = Number(length)
      if (length > remaining) {
        length = remaining
      }
    }
    encoding = String(encoding || 'utf8').toLowerCase()
  
    var ret
    switch (encoding) {
      case 'hex':
        ret = hexWrite(this, string, offset, length)
        break
      case 'utf8':
      case 'utf-8':
        ret = utf8Write(this, string, offset, length)
        break
      case 'ascii':
        ret = asciiWrite(this, string, offset, length)
        break
      case 'binary':
        ret = binaryWrite(this, string, offset, length)
        break
      case 'base64':
        ret = base64Write(this, string, offset, length)
        break
      case 'ucs2':
      case 'ucs-2':
      case 'utf16le':
      case 'utf-16le':
        ret = utf16leWrite(this, string, offset, length)
        break
      default:
        throw new TypeError('Unknown encoding: ' + encoding)
    }
    return ret
  }
  
  Buffer.prototype.toJSON = function () {
    return {
      type: 'Buffer',
      data: Array.prototype.slice.call(this._arr || this, 0)
    }
  }
  
  function base64Slice (buf, start, end) {
    if (start === 0 && end === buf.length) {
      return base64.fromByteArray(buf)
    } else {
      return base64.fromByteArray(buf.slice(start, end))
    }
  }
  
  function utf8Slice (buf, start, end) {
    var res = ''
    var tmp = ''
    end = Math.min(buf.length, end)
  
    for (var i = start; i < end; i++) {
      if (buf[i] <= 0x7F) {
        res += decodeUtf8Char(tmp) + String.fromCharCode(buf[i])
        tmp = ''
      } else {
        tmp += '%' + buf[i].toString(16)
      }
    }
  
    return res + decodeUtf8Char(tmp)
  }
  
  function asciiSlice (buf, start, end) {
    var ret = ''
    end = Math.min(buf.length, end)
  
    for (var i = start; i < end; i++) {
      ret += String.fromCharCode(buf[i] & 0x7F)
    }
    return ret
  }
  
  function binarySlice (buf, start, end) {
    var ret = ''
    end = Math.min(buf.length, end)
  
    for (var i = start; i < end; i++) {
      ret += String.fromCharCode(buf[i])
    }
    return ret
  }
  
  function hexSlice (buf, start, end) {
    var len = buf.length
  
    if (!start || start < 0) start = 0
    if (!end || end < 0 || end > len) end = len
  
    var out = ''
    for (var i = start; i < end; i++) {
      out += toHex(buf[i])
    }
    return out
  }
  
  function utf16leSlice (buf, start, end) {
    var bytes = buf.slice(start, end)
    var res = ''
    for (var i = 0; i < bytes.length; i += 2) {
      res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256)
    }
    return res
  }
  
  Buffer.prototype.slice = function (start, end) {
    var len = this.length
    start = ~~start
    end = end === undefined ? len : ~~end
  
    if (start < 0) {
      start += len;
      if (start < 0)
        start = 0
    } else if (start > len) {
      start = len
    }
  
    if (end < 0) {
      end += len
      if (end < 0)
        end = 0
    } else if (end > len) {
      end = len
    }
  
    if (end < start)
      end = start
  
    var newBuf
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      newBuf = Buffer._augment(this.subarray(start, end))
    } else {
      var sliceLen = end - start
      newBuf = new Buffer(sliceLen, undefined, true)
      for (var i = 0; i < sliceLen; i++) {
        newBuf[i] = this[i + start]
      }
    }
  
    if (newBuf.length)
      newBuf.parent = this.parent || this
  
    return newBuf
  }
  
  /*
   * Need to make sure that buffer isn't trying to write out of bounds.
   */
  function checkOffset (offset, ext, length) {
    if ((offset % 1) !== 0 || offset < 0)
      throw new RangeError('offset is not uint')
    if (offset + ext > length)
      throw new RangeError('Trying to access beyond buffer length')
  }
  
  Buffer.prototype.readUIntLE = function (offset, byteLength, noAssert) {
    offset = offset >>> 0
    byteLength = byteLength >>> 0
    if (!noAssert)
      checkOffset(offset, byteLength, this.length)
  
    var val = this[offset]
    var mul = 1
    var i = 0
    while (++i < byteLength && (mul *= 0x100))
      val += this[offset + i] * mul
  
    return val
  }
  
  Buffer.prototype.readUIntBE = function (offset, byteLength, noAssert) {
    offset = offset >>> 0
    byteLength = byteLength >>> 0
    if (!noAssert)
      checkOffset(offset, byteLength, this.length)
  
    var val = this[offset + --byteLength]
    var mul = 1
    while (byteLength > 0 && (mul *= 0x100))
      val += this[offset + --byteLength] * mul;
  
    return val
  }
  
  Buffer.prototype.readUInt8 = function (offset, noAssert) {
    if (!noAssert)
      checkOffset(offset, 1, this.length)
    return this[offset]
  }
  
  Buffer.prototype.readUInt16LE = function (offset, noAssert) {
    if (!noAssert)
      checkOffset(offset, 2, this.length)
    return this[offset] | (this[offset + 1] << 8)
  }
  
  Buffer.prototype.readUInt16BE = function (offset, noAssert) {
    if (!noAssert)
      checkOffset(offset, 2, this.length)
    return (this[offset] << 8) | this[offset + 1]
  }
  
  Buffer.prototype.readUInt32LE = function (offset, noAssert) {
    if (!noAssert)
      checkOffset(offset, 4, this.length)
  
    return ((this[offset]) |
        (this[offset + 1] << 8) |
        (this[offset + 2] << 16)) +
        (this[offset + 3] * 0x1000000)
  }
  
  Buffer.prototype.readUInt32BE = function (offset, noAssert) {
    if (!noAssert)
      checkOffset(offset, 4, this.length)
  
    return (this[offset] * 0x1000000) +
        ((this[offset + 1] << 16) |
        (this[offset + 2] << 8) |
        this[offset + 3])
  }
  
  Buffer.prototype.readIntLE = function (offset, byteLength, noAssert) {
    offset = offset >>> 0
    byteLength = byteLength >>> 0
    if (!noAssert)
      checkOffset(offset, byteLength, this.length)
  
    var val = this[offset]
    var mul = 1
    var i = 0
    while (++i < byteLength && (mul *= 0x100))
      val += this[offset + i] * mul
    mul *= 0x80
  
    if (val >= mul)
      val -= Math.pow(2, 8 * byteLength)
  
    return val
  }
  
  Buffer.prototype.readIntBE = function (offset, byteLength, noAssert) {
    offset = offset >>> 0
    byteLength = byteLength >>> 0
    if (!noAssert)
      checkOffset(offset, byteLength, this.length)
  
    var i = byteLength
    var mul = 1
    var val = this[offset + --i]
    while (i > 0 && (mul *= 0x100))
      val += this[offset + --i] * mul
    mul *= 0x80
  
    if (val >= mul)
      val -= Math.pow(2, 8 * byteLength)
  
    return val
  }
  
  Buffer.prototype.readInt8 = function (offset, noAssert) {
    if (!noAssert)
      checkOffset(offset, 1, this.length)
    if (!(this[offset] & 0x80))
      return (this[offset])
    return ((0xff - this[offset] + 1) * -1)
  }
  
  Buffer.prototype.readInt16LE = function (offset, noAssert) {
    if (!noAssert)
      checkOffset(offset, 2, this.length)
    var val = this[offset] | (this[offset + 1] << 8)
    return (val & 0x8000) ? val | 0xFFFF0000 : val
  }
  
  Buffer.prototype.readInt16BE = function (offset, noAssert) {
    if (!noAssert)
      checkOffset(offset, 2, this.length)
    var val = this[offset + 1] | (this[offset] << 8)
    return (val & 0x8000) ? val | 0xFFFF0000 : val
  }
  
  Buffer.prototype.readInt32LE = function (offset, noAssert) {
    if (!noAssert)
      checkOffset(offset, 4, this.length)
  
    return (this[offset]) |
        (this[offset + 1] << 8) |
        (this[offset + 2] << 16) |
        (this[offset + 3] << 24)
  }
  
  Buffer.prototype.readInt32BE = function (offset, noAssert) {
    if (!noAssert)
      checkOffset(offset, 4, this.length)
  
    return (this[offset] << 24) |
        (this[offset + 1] << 16) |
        (this[offset + 2] << 8) |
        (this[offset + 3])
  }
  
  Buffer.prototype.readFloatLE = function (offset, noAssert) {
    if (!noAssert)
      checkOffset(offset, 4, this.length)
    return ieee754.read(this, offset, true, 23, 4)
  }
  
  Buffer.prototype.readFloatBE = function (offset, noAssert) {
    if (!noAssert)
      checkOffset(offset, 4, this.length)
    return ieee754.read(this, offset, false, 23, 4)
  }
  
  Buffer.prototype.readDoubleLE = function (offset, noAssert) {
    if (!noAssert)
      checkOffset(offset, 8, this.length)
    return ieee754.read(this, offset, true, 52, 8)
  }
  
  Buffer.prototype.readDoubleBE = function (offset, noAssert) {
    if (!noAssert)
      checkOffset(offset, 8, this.length)
    return ieee754.read(this, offset, false, 52, 8)
  }
  
  function checkInt (buf, value, offset, ext, max, min) {
    if (!Buffer.isBuffer(buf)) throw new TypeError('buffer must be a Buffer instance')
    if (value > max || value < min) throw new RangeError('value is out of bounds')
    if (offset + ext > buf.length) throw new RangeError('index out of range')
  }
  
  Buffer.prototype.writeUIntLE = function (value, offset, byteLength, noAssert) {
    value = +value
    offset = offset >>> 0
    byteLength = byteLength >>> 0
    if (!noAssert)
      checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0)
  
    var mul = 1
    var i = 0
    this[offset] = value & 0xFF
    while (++i < byteLength && (mul *= 0x100))
      this[offset + i] = (value / mul) >>> 0 & 0xFF
  
    return offset + byteLength
  }
  
  Buffer.prototype.writeUIntBE = function (value, offset, byteLength, noAssert) {
    value = +value
    offset = offset >>> 0
    byteLength = byteLength >>> 0
    if (!noAssert)
      checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0)
  
    var i = byteLength - 1
    var mul = 1
    this[offset + i] = value & 0xFF
    while (--i >= 0 && (mul *= 0x100))
      this[offset + i] = (value / mul) >>> 0 & 0xFF
  
    return offset + byteLength
  }
  
  Buffer.prototype.writeUInt8 = function (value, offset, noAssert) {
    value = +value
    offset = offset >>> 0
    if (!noAssert)
      checkInt(this, value, offset, 1, 0xff, 0)
    if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
    this[offset] = value
    return offset + 1
  }
  
  function objectWriteUInt16 (buf, value, offset, littleEndian) {
    if (value < 0) value = 0xffff + value + 1
    for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; i++) {
      buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>>
        (littleEndian ? i : 1 - i) * 8
    }
  }
  
  Buffer.prototype.writeUInt16LE = function (value, offset, noAssert) {
    value = +value
    offset = offset >>> 0
    if (!noAssert)
      checkInt(this, value, offset, 2, 0xffff, 0)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = value
      this[offset + 1] = (value >>> 8)
    } else objectWriteUInt16(this, value, offset, true)
    return offset + 2
  }
  
  Buffer.prototype.writeUInt16BE = function (value, offset, noAssert) {
    value = +value
    offset = offset >>> 0
    if (!noAssert)
      checkInt(this, value, offset, 2, 0xffff, 0)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = (value >>> 8)
      this[offset + 1] = value
    } else objectWriteUInt16(this, value, offset, false)
    return offset + 2
  }
  
  function objectWriteUInt32 (buf, value, offset, littleEndian) {
    if (value < 0) value = 0xffffffff + value + 1
    for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; i++) {
      buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff
    }
  }
  
  Buffer.prototype.writeUInt32LE = function (value, offset, noAssert) {
    value = +value
    offset = offset >>> 0
    if (!noAssert)
      checkInt(this, value, offset, 4, 0xffffffff, 0)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset + 3] = (value >>> 24)
      this[offset + 2] = (value >>> 16)
      this[offset + 1] = (value >>> 8)
      this[offset] = value
    } else objectWriteUInt32(this, value, offset, true)
    return offset + 4
  }
  
  Buffer.prototype.writeUInt32BE = function (value, offset, noAssert) {
    value = +value
    offset = offset >>> 0
    if (!noAssert)
      checkInt(this, value, offset, 4, 0xffffffff, 0)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = (value >>> 24)
      this[offset + 1] = (value >>> 16)
      this[offset + 2] = (value >>> 8)
      this[offset + 3] = value
    } else objectWriteUInt32(this, value, offset, false)
    return offset + 4
  }
  
  Buffer.prototype.writeIntLE = function (value, offset, byteLength, noAssert) {
    value = +value
    offset = offset >>> 0
    if (!noAssert) {
      checkInt(this,
               value,
               offset,
               byteLength,
               Math.pow(2, 8 * byteLength - 1) - 1,
               -Math.pow(2, 8 * byteLength - 1))
    }
  
    var i = 0
    var mul = 1
    var sub = value < 0 ? 1 : 0
    this[offset] = value & 0xFF
    while (++i < byteLength && (mul *= 0x100))
      this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
  
    return offset + byteLength
  }
  
  Buffer.prototype.writeIntBE = function (value, offset, byteLength, noAssert) {
    value = +value
    offset = offset >>> 0
    if (!noAssert) {
      checkInt(this,
               value,
               offset,
               byteLength,
               Math.pow(2, 8 * byteLength - 1) - 1,
               -Math.pow(2, 8 * byteLength - 1))
    }
  
    var i = byteLength - 1
    var mul = 1
    var sub = value < 0 ? 1 : 0
    this[offset + i] = value & 0xFF
    while (--i >= 0 && (mul *= 0x100))
      this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
  
    return offset + byteLength
  }
  
  Buffer.prototype.writeInt8 = function (value, offset, noAssert) {
    value = +value
    offset = offset >>> 0
    if (!noAssert)
      checkInt(this, value, offset, 1, 0x7f, -0x80)
    if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
    if (value < 0) value = 0xff + value + 1
    this[offset] = value
    return offset + 1
  }
  
  Buffer.prototype.writeInt16LE = function (value, offset, noAssert) {
    value = +value
    offset = offset >>> 0
    if (!noAssert)
      checkInt(this, value, offset, 2, 0x7fff, -0x8000)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = value
      this[offset + 1] = (value >>> 8)
    } else objectWriteUInt16(this, value, offset, true)
    return offset + 2
  }
  
  Buffer.prototype.writeInt16BE = function (value, offset, noAssert) {
    value = +value
    offset = offset >>> 0
    if (!noAssert)
      checkInt(this, value, offset, 2, 0x7fff, -0x8000)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = (value >>> 8)
      this[offset + 1] = value
    } else objectWriteUInt16(this, value, offset, false)
    return offset + 2
  }
  
  Buffer.prototype.writeInt32LE = function (value, offset, noAssert) {
    value = +value
    offset = offset >>> 0
    if (!noAssert)
      checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = value
      this[offset + 1] = (value >>> 8)
      this[offset + 2] = (value >>> 16)
      this[offset + 3] = (value >>> 24)
    } else objectWriteUInt32(this, value, offset, true)
    return offset + 4
  }
  
  Buffer.prototype.writeInt32BE = function (value, offset, noAssert) {
    value = +value
    offset = offset >>> 0
    if (!noAssert)
      checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
    if (value < 0) value = 0xffffffff + value + 1
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = (value >>> 24)
      this[offset + 1] = (value >>> 16)
      this[offset + 2] = (value >>> 8)
      this[offset + 3] = value
    } else objectWriteUInt32(this, value, offset, false)
    return offset + 4
  }
  
  function checkIEEE754 (buf, value, offset, ext, max, min) {
    if (value > max || value < min) throw new RangeError('value is out of bounds')
    if (offset + ext > buf.length) throw new RangeError('index out of range')
    if (offset < 0) throw new RangeError('index out of range')
  }
  
  function writeFloat (buf, value, offset, littleEndian, noAssert) {
    if (!noAssert)
      checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38)
    ieee754.write(buf, value, offset, littleEndian, 23, 4)
    return offset + 4
  }
  
  Buffer.prototype.writeFloatLE = function (value, offset, noAssert) {
    return writeFloat(this, value, offset, true, noAssert)
  }
  
  Buffer.prototype.writeFloatBE = function (value, offset, noAssert) {
    return writeFloat(this, value, offset, false, noAssert)
  }
  
  function writeDouble (buf, value, offset, littleEndian, noAssert) {
    if (!noAssert)
      checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308)
    ieee754.write(buf, value, offset, littleEndian, 52, 8)
    return offset + 8
  }
  
  Buffer.prototype.writeDoubleLE = function (value, offset, noAssert) {
    return writeDouble(this, value, offset, true, noAssert)
  }
  
  Buffer.prototype.writeDoubleBE = function (value, offset, noAssert) {
    return writeDouble(this, value, offset, false, noAssert)
  }
  
  // copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
  Buffer.prototype.copy = function (target, target_start, start, end) {
    var source = this
  
    if (!start) start = 0
    if (!end && end !== 0) end = this.length
    if (target_start >= target.length) target_start = target.length
    if (!target_start) target_start = 0
    if (end > 0 && end < start) end = start
  
    // Copy 0 bytes; we're done
    if (end === start) return 0
    if (target.length === 0 || source.length === 0) return 0
  
    // Fatal error conditions
    if (target_start < 0)
      throw new RangeError('targetStart out of bounds')
    if (start < 0 || start >= source.length) throw new RangeError('sourceStart out of bounds')
    if (end < 0) throw new RangeError('sourceEnd out of bounds')
  
    // Are we oob?
    if (end > this.length)
      end = this.length
    if (target.length - target_start < end - start)
      end = target.length - target_start + start
  
    var len = end - start
  
    if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) {
      for (var i = 0; i < len; i++) {
        target[i + target_start] = this[i + start]
      }
    } else {
      target._set(this.subarray(start, start + len), target_start)
    }
  
    return len
  }
  
  // fill(value, start=0, end=buffer.length)
  Buffer.prototype.fill = function (value, start, end) {
    if (!value) value = 0
    if (!start) start = 0
    if (!end) end = this.length
  
    if (end < start) throw new RangeError('end < start')
  
    // Fill 0 bytes; we're done
    if (end === start) return
    if (this.length === 0) return
  
    if (start < 0 || start >= this.length) throw new RangeError('start out of bounds')
    if (end < 0 || end > this.length) throw new RangeError('end out of bounds')
  
    var i
    if (typeof value === 'number') {
      for (i = start; i < end; i++) {
        this[i] = value
      }
    } else {
      var bytes = utf8ToBytes(value.toString())
      var len = bytes.length
      for (i = start; i < end; i++) {
        this[i] = bytes[i % len]
      }
    }
  
    return this
  }
  
  /**
   * Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance.
   * Added in Node 0.12. Only available in browsers that support ArrayBuffer.
   */
  Buffer.prototype.toArrayBuffer = function () {
    if (typeof Uint8Array !== 'undefined') {
      if (Buffer.TYPED_ARRAY_SUPPORT) {
        return (new Buffer(this)).buffer
      } else {
        var buf = new Uint8Array(this.length)
        for (var i = 0, len = buf.length; i < len; i += 1) {
          buf[i] = this[i]
        }
        return buf.buffer
      }
    } else {
      throw new TypeError('Buffer.toArrayBuffer not supported in this browser')
    }
  }
  
  // HELPER FUNCTIONS
  // ================
  
  var BP = Buffer.prototype
  
  /**
   * Augment a Uint8Array *instance* (not the Uint8Array class!) with Buffer methods
   */
  Buffer._augment = function (arr) {
    arr.constructor = Buffer
    arr._isBuffer = true
  
    // save reference to original Uint8Array get/set methods before overwriting
    arr._get = arr.get
    arr._set = arr.set
  
    // deprecated, will be removed in node 0.13+
    arr.get = BP.get
    arr.set = BP.set
  
    arr.write = BP.write
    arr.toString = BP.toString
    arr.toLocaleString = BP.toString
    arr.toJSON = BP.toJSON
    arr.equals = BP.equals
    arr.compare = BP.compare
    arr.copy = BP.copy
    arr.slice = BP.slice
    arr.readUIntLE = BP.readUIntLE
    arr.readUIntBE = BP.readUIntBE
    arr.readUInt8 = BP.readUInt8
    arr.readUInt16LE = BP.readUInt16LE
    arr.readUInt16BE = BP.readUInt16BE
    arr.readUInt32LE = BP.readUInt32LE
    arr.readUInt32BE = BP.readUInt32BE
    arr.readIntLE = BP.readIntLE
    arr.readIntBE = BP.readIntBE
    arr.readInt8 = BP.readInt8
    arr.readInt16LE = BP.readInt16LE
    arr.readInt16BE = BP.readInt16BE
    arr.readInt32LE = BP.readInt32LE
    arr.readInt32BE = BP.readInt32BE
    arr.readFloatLE = BP.readFloatLE
    arr.readFloatBE = BP.readFloatBE
    arr.readDoubleLE = BP.readDoubleLE
    arr.readDoubleBE = BP.readDoubleBE
    arr.writeUInt8 = BP.writeUInt8
    arr.writeUIntLE = BP.writeUIntLE
    arr.writeUIntBE = BP.writeUIntBE
    arr.writeUInt16LE = BP.writeUInt16LE
    arr.writeUInt16BE = BP.writeUInt16BE
    arr.writeUInt32LE = BP.writeUInt32LE
    arr.writeUInt32BE = BP.writeUInt32BE
    arr.writeIntLE = BP.writeIntLE
    arr.writeIntBE = BP.writeIntBE
    arr.writeInt8 = BP.writeInt8
    arr.writeInt16LE = BP.writeInt16LE
    arr.writeInt16BE = BP.writeInt16BE
    arr.writeInt32LE = BP.writeInt32LE
    arr.writeInt32BE = BP.writeInt32BE
    arr.writeFloatLE = BP.writeFloatLE
    arr.writeFloatBE = BP.writeFloatBE
    arr.writeDoubleLE = BP.writeDoubleLE
    arr.writeDoubleBE = BP.writeDoubleBE
    arr.fill = BP.fill
    arr.inspect = BP.inspect
    arr.toArrayBuffer = BP.toArrayBuffer
  
    return arr
  }
  
  var INVALID_BASE64_RE = /[^+\/0-9A-z\-]/g
  
  function base64clean (str) {
    // Node strips out invalid characters like \n and \t from the string, base64-js does not
    str = stringtrim(str).replace(INVALID_BASE64_RE, '')
    // Node converts strings with length < 2 to ''
    if (str.length < 2) return ''
    // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not
    while (str.length % 4 !== 0) {
      str = str + '='
    }
    return str
  }
  
  function stringtrim (str) {
    if (str.trim) return str.trim()
    return str.replace(/^\s+|\s+$/g, '')
  }
  
  function isArrayish (subject) {
    return isArray(subject) || Buffer.isBuffer(subject) ||
        subject && typeof subject === 'object' &&
        typeof subject.length === 'number'
  }
  
  function toHex (n) {
    if (n < 16) return '0' + n.toString(16)
    return n.toString(16)
  }
  
  function utf8ToBytes(string, units) {
    var codePoint, length = string.length
    var leadSurrogate = null
    units = units || Infinity
    var bytes = []
    var i = 0
  
    for (; i<length; i++) {
      codePoint = string.charCodeAt(i)
  
      // is surrogate component
      if (codePoint > 0xD7FF && codePoint < 0xE000) {
  
        // last char was a lead
        if (leadSurrogate) {
  
          // 2 leads in a row
          if (codePoint < 0xDC00) {
            if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
            leadSurrogate = codePoint
            continue
          }
  
          // valid surrogate pair
          else {
            codePoint = leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00 | 0x10000
            leadSurrogate = null
          }
        }
  
        // no lead yet
        else {
  
          // unexpected trail
          if (codePoint > 0xDBFF) {
            if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
            continue
          }
  
          // unpaired lead
          else if (i + 1 === length) {
            if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
            continue
          }
  
          // valid lead
          else {
            leadSurrogate = codePoint
            continue
          }
        }
      }
  
      // valid bmp char, but last char was a lead
      else if (leadSurrogate) {
        if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
        leadSurrogate = null
      }
  
      // encode utf8
      if (codePoint < 0x80) {
        if ((units -= 1) < 0) break
        bytes.push(codePoint)
      }
      else if (codePoint < 0x800) {
        if ((units -= 2) < 0) break
        bytes.push(
          codePoint >> 0x6 | 0xC0,
          codePoint & 0x3F | 0x80
        );
      }
      else if (codePoint < 0x10000) {
        if ((units -= 3) < 0) break
        bytes.push(
          codePoint >> 0xC | 0xE0,
          codePoint >> 0x6 & 0x3F | 0x80,
          codePoint & 0x3F | 0x80
        );
      }
      else if (codePoint < 0x200000) {
        if ((units -= 4) < 0) break
        bytes.push(
          codePoint >> 0x12 | 0xF0,
          codePoint >> 0xC & 0x3F | 0x80,
          codePoint >> 0x6 & 0x3F | 0x80,
          codePoint & 0x3F | 0x80
        );
      }
      else {
        throw new Error('Invalid code point')
      }
    }
  
    return bytes
  }
  
  function asciiToBytes (str) {
    var byteArray = []
    for (var i = 0; i < str.length; i++) {
      // Node's code seems to be doing this and not & 0x7F..
      byteArray.push(str.charCodeAt(i) & 0xFF)
    }
    return byteArray
  }
  
  function utf16leToBytes (str, units) {
    var c, hi, lo
    var byteArray = []
    for (var i = 0; i < str.length; i++) {
  
      if ((units -= 2) < 0) break
  
      c = str.charCodeAt(i)
      hi = c >> 8
      lo = c % 256
      byteArray.push(lo)
      byteArray.push(hi)
    }
  
    return byteArray
  }
  
  function base64ToBytes (str) {
    return base64.toByteArray(base64clean(str))
  }
  
  function blitBuffer (src, dst, offset, length, unitSize) {
    if (unitSize) length -= length % unitSize;
    for (var i = 0; i < length; i++) {
      if ((i + offset >= dst.length) || (i >= src.length))
        break
      dst[i + offset] = src[i]
    }
    return i
  }
  
  function decodeUtf8Char (str) {
    try {
      return decodeURIComponent(str)
    } catch (err) {
      return String.fromCharCode(0xFFFD) // UTF 8 invalid char
    }
  }
  
  },{"base64-js":43,"ieee754":44,"is-array":45}],43:[function(require,module,exports){
  var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
  
  ;(function (exports) {
  	'use strict';
  
    var Arr = (typeof Uint8Array !== 'undefined')
      ? Uint8Array
      : Array
  
  	var PLUS   = '+'.charCodeAt(0)
  	var SLASH  = '/'.charCodeAt(0)
  	var NUMBER = '0'.charCodeAt(0)
  	var LOWER  = 'a'.charCodeAt(0)
  	var UPPER  = 'A'.charCodeAt(0)
  	var PLUS_URL_SAFE = '-'.charCodeAt(0)
  	var SLASH_URL_SAFE = '_'.charCodeAt(0)
  
  	function decode (elt) {
  		var code = elt.charCodeAt(0)
  		if (code === PLUS ||
  		    code === PLUS_URL_SAFE)
  			return 62 // '+'
  		if (code === SLASH ||
  		    code === SLASH_URL_SAFE)
  			return 63 // '/'
  		if (code < NUMBER)
  			return -1 //no match
  		if (code < NUMBER + 10)
  			return code - NUMBER + 26 + 26
  		if (code < UPPER + 26)
  			return code - UPPER
  		if (code < LOWER + 26)
  			return code - LOWER + 26
  	}
  
  	function b64ToByteArray (b64) {
  		var i, j, l, tmp, placeHolders, arr
  
  		if (b64.length % 4 > 0) {
  			throw new Error('Invalid string. Length must be a multiple of 4')
  		}
  
  		// the number of equal signs (place holders)
  		// if there are two placeholders, than the two characters before it
  		// represent one byte
  		// if there is only one, then the three characters before it represent 2 bytes
  		// this is just a cheap hack to not do indexOf twice
  		var len = b64.length
  		placeHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0
  
  		// base64 is 4/3 + up to two characters of the original data
  		arr = new Arr(b64.length * 3 / 4 - placeHolders)
  
  		// if there are placeholders, only get up to the last complete 4 chars
  		l = placeHolders > 0 ? b64.length - 4 : b64.length
  
  		var L = 0
  
  		function push (v) {
  			arr[L++] = v
  		}
  
  		for (i = 0, j = 0; i < l; i += 4, j += 3) {
  			tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3))
  			push((tmp & 0xFF0000) >> 16)
  			push((tmp & 0xFF00) >> 8)
  			push(tmp & 0xFF)
  		}
  
  		if (placeHolders === 2) {
  			tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4)
  			push(tmp & 0xFF)
  		} else if (placeHolders === 1) {
  			tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2)
  			push((tmp >> 8) & 0xFF)
  			push(tmp & 0xFF)
  		}
  
  		return arr
  	}
  
  	function uint8ToBase64 (uint8) {
  		var i,
  			extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes
  			output = "",
  			temp, length
  
  		function encode (num) {
  			return lookup.charAt(num)
  		}
  
  		function tripletToBase64 (num) {
  			return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F)
  		}
  
  		// go through the array every three bytes, we'll deal with trailing stuff later
  		for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) {
  			temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])
  			output += tripletToBase64(temp)
  		}
  
  		// pad the end with zeros, but make sure to not forget the extra bytes
  		switch (extraBytes) {
  			case 1:
  				temp = uint8[uint8.length - 1]
  				output += encode(temp >> 2)
  				output += encode((temp << 4) & 0x3F)
  				output += '=='
  				break
  			case 2:
  				temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1])
  				output += encode(temp >> 10)
  				output += encode((temp >> 4) & 0x3F)
  				output += encode((temp << 2) & 0x3F)
  				output += '='
  				break
  		}
  
  		return output
  	}
  
  	exports.toByteArray = b64ToByteArray
  	exports.fromByteArray = uint8ToBase64
  }(typeof exports === 'undefined' ? (this.base64js = {}) : exports))
  
  },{}],44:[function(require,module,exports){
  exports.read = function(buffer, offset, isLE, mLen, nBytes) {
    var e, m,
        eLen = nBytes * 8 - mLen - 1,
        eMax = (1 << eLen) - 1,
        eBias = eMax >> 1,
        nBits = -7,
        i = isLE ? (nBytes - 1) : 0,
        d = isLE ? -1 : 1,
        s = buffer[offset + i];
  
    i += d;
  
    e = s & ((1 << (-nBits)) - 1);
    s >>= (-nBits);
    nBits += eLen;
    for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8);
  
    m = e & ((1 << (-nBits)) - 1);
    e >>= (-nBits);
    nBits += mLen;
    for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8);
  
    if (e === 0) {
      e = 1 - eBias;
    } else if (e === eMax) {
      return m ? NaN : ((s ? -1 : 1) * Infinity);
    } else {
      m = m + Math.pow(2, mLen);
      e = e - eBias;
    }
    return (s ? -1 : 1) * m * Math.pow(2, e - mLen);
  };
  
  exports.write = function(buffer, value, offset, isLE, mLen, nBytes) {
    var e, m, c,
        eLen = nBytes * 8 - mLen - 1,
        eMax = (1 << eLen) - 1,
        eBias = eMax >> 1,
        rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0),
        i = isLE ? 0 : (nBytes - 1),
        d = isLE ? 1 : -1,
        s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0;
  
    value = Math.abs(value);
  
    if (isNaN(value) || value === Infinity) {
      m = isNaN(value) ? 1 : 0;
      e = eMax;
    } else {
      e = Math.floor(Math.log(value) / Math.LN2);
      if (value * (c = Math.pow(2, -e)) < 1) {
        e--;
        c *= 2;
      }
      if (e + eBias >= 1) {
        value += rt / c;
      } else {
        value += rt * Math.pow(2, 1 - eBias);
      }
      if (value * c >= 2) {
        e++;
        c /= 2;
      }
  
      if (e + eBias >= eMax) {
        m = 0;
        e = eMax;
      } else if (e + eBias >= 1) {
        m = (value * c - 1) * Math.pow(2, mLen);
        e = e + eBias;
      } else {
        m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen);
        e = 0;
      }
    }
  
    for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8);
  
    e = (e << mLen) | m;
    eLen += mLen;
    for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8);
  
    buffer[offset + i - d] |= s * 128;
  };
  
  },{}],45:[function(require,module,exports){
  
  /**
   * isArray
   */
  
  var isArray = Array.isArray;
  
  /**
   * toString
   */
  
  var str = Object.prototype.toString;
  
  /**
   * Whether or not the given `val`
   * is an array.
   *
   * example:
   *
   *        isArray([]);
   *        // > true
   *        isArray(arguments);
   *        // > false
   *        isArray('');
   *        // > false
   *
   * @param {mixed} val
   * @return {bool}
   */
  
  module.exports = isArray || function (val) {
    return !! val && '[object Array]' == str.call(val);
  };
  
  },{}],46:[function(require,module,exports){
  // 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.
  
  function EventEmitter() {
    this._events = this._events || {};
    this._maxListeners = this._maxListeners || undefined;
  }
  module.exports = EventEmitter;
  
  // Backwards-compat with node 0.10.x
  EventEmitter.EventEmitter = EventEmitter;
  
  EventEmitter.prototype._events = undefined;
  EventEmitter.prototype._maxListeners = undefined;
  
  // By default EventEmitters will print a warning if more than 10 listeners are
  // added to it. This is a useful default which helps finding memory leaks.
  EventEmitter.defaultMaxListeners = 10;
  
  // Obviously not all Emitters should be limited to 10. This function allows
  // that to be increased. Set to zero for unlimited.
  EventEmitter.prototype.setMaxListeners = function(n) {
    if (!isNumber(n) || n < 0 || isNaN(n))
      throw TypeError('n must be a positive number');
    this._maxListeners = n;
    return this;
  };
  
  EventEmitter.prototype.emit = function(type) {
    var er, handler, len, args, i, listeners;
  
    if (!this._events)
      this._events = {};
  
    // If there is no 'error' event listener then throw.
    if (type === 'error') {
      if (!this._events.error ||
          (isObject(this._events.error) && !this._events.error.length)) {
        er = arguments[1];
        if (er instanceof Error) {
          throw er; // Unhandled 'error' event
        }
        throw TypeError('Uncaught, unspecified "error" event.');
      }
    }
  
    handler = this._events[type];
  
    if (isUndefined(handler))
      return false;
  
    if (isFunction(handler)) {
      switch (arguments.length) {
        // fast cases
        case 1:
          handler.call(this);
          break;
        case 2:
          handler.call(this, arguments[1]);
          break;
        case 3:
          handler.call(this, arguments[1], arguments[2]);
          break;
        // slower
        default:
          len = arguments.length;
          args = new Array(len - 1);
          for (i = 1; i < len; i++)
            args[i - 1] = arguments[i];
          handler.apply(this, args);
      }
    } else if (isObject(handler)) {
      len = arguments.length;
      args = new Array(len - 1);
      for (i = 1; i < len; i++)
        args[i - 1] = arguments[i];
  
      listeners = handler.slice();
      len = listeners.length;
      for (i = 0; i < len; i++)
        listeners[i].apply(this, args);
    }
  
    return true;
  };
  
  EventEmitter.prototype.addListener = function(type, listener) {
    var m;
  
    if (!isFunction(listener))
      throw TypeError('listener must be a function');
  
    if (!this._events)
      this._events = {};
  
    // To avoid recursion in the case that type === "newListener"! Before
    // adding it to the listeners, first emit "newListener".
    if (this._events.newListener)
      this.emit('newListener', type,
                isFunction(listener.listener) ?
                listener.listener : listener);
  
    if (!this._events[type])
      // Optimize the case of one listener. Don't need the extra array object.
      this._events[type] = listener;
    else if (isObject(this._events[type]))
      // If we've already got an array, just append.
      this._events[type].push(listener);
    else
      // Adding the second element, need to change to array.
      this._events[type] = [this._events[type], listener];
  
    // Check for listener leak
    if (isObject(this._events[type]) && !this._events[type].warned) {
      var m;
      if (!isUndefined(this._maxListeners)) {
        m = this._maxListeners;
      } else {
        m = EventEmitter.defaultMaxListeners;
      }
  
      if (m && m > 0 && this._events[type].length > m) {
        this._events[type].warned = true;
        console.error('(node) warning: possible EventEmitter memory ' +
                      'leak detected. %d listeners added. ' +
                      'Use emitter.setMaxListeners() to increase limit.',
                      this._events[type].length);
        if (typeof console.trace === 'function') {
          // not supported in IE 10
          console.trace();
        }
      }
    }
  
    return this;
  };
  
  EventEmitter.prototype.on = EventEmitter.prototype.addListener;
  
  EventEmitter.prototype.once = function(type, listener) {
    if (!isFunction(listener))
      throw TypeError('listener must be a function');
  
    var fired = false;
  
    function g() {
      this.removeListener(type, g);
  
      if (!fired) {
        fired = true;
        listener.apply(this, arguments);
      }
    }
  
    g.listener = listener;
    this.on(type, g);
  
    return this;
  };
  
  // emits a 'removeListener' event iff the listener was removed
  EventEmitter.prototype.removeListener = function(type, listener) {
    var list, position, length, i;
  
    if (!isFunction(listener))
      throw TypeError('listener must be a function');
  
    if (!this._events || !this._events[type])
      return this;
  
    list = this._events[type];
    length = list.length;
    position = -1;
  
    if (list === listener ||
        (isFunction(list.listener) && list.listener === listener)) {
      delete this._events[type];
      if (this._events.removeListener)
        this.emit('removeListener', type, listener);
  
    } else if (isObject(list)) {
      for (i = length; i-- > 0;) {
        if (list[i] === listener ||
            (list[i].listener && list[i].listener === listener)) {
          position = i;
          break;
        }
      }
  
      if (position < 0)
        return this;
  
      if (list.length === 1) {
        list.length = 0;
        delete this._events[type];
      } else {
        list.splice(position, 1);
      }
  
      if (this._events.removeListener)
        this.emit('removeListener', type, listener);
    }
  
    return this;
  };
  
  EventEmitter.prototype.removeAllListeners = function(type) {
    var key, listeners;
  
    if (!this._events)
      return this;
  
    // not listening for removeListener, no need to emit
    if (!this._events.removeListener) {
      if (arguments.length === 0)
        this._events = {};
      else if (this._events[type])
        delete this._events[type];
      return this;
    }
  
    // emit removeListener for all listeners on all events
    if (arguments.length === 0) {
      for (key in this._events) {
        if (key === 'removeListener') continue;
        this.removeAllListeners(key);
      }
      this.removeAllListeners('removeListener');
      this._events = {};
      return this;
    }
  
    listeners = this._events[type];
  
    if (isFunction(listeners)) {
      this.removeListener(type, listeners);
    } else {
      // LIFO order
      while (listeners.length)
        this.removeListener(type, listeners[listeners.length - 1]);
    }
    delete this._events[type];
  
    return this;
  };
  
  EventEmitter.prototype.listeners = function(type) {
    var ret;
    if (!this._events || !this._events[type])
      ret = [];
    else if (isFunction(this._events[type]))
      ret = [this._events[type]];
    else
      ret = this._events[type].slice();
    return ret;
  };
  
  EventEmitter.listenerCount = function(emitter, type) {
    var ret;
    if (!emitter._events || !emitter._events[type])
      ret = 0;
    else if (isFunction(emitter._events[type]))
      ret = 1;
    else
      ret = emitter._events[type].length;
    return ret;
  };
  
  function isFunction(arg) {
    return typeof arg === 'function';
  }
  
  function isNumber(arg) {
    return typeof arg === 'number';
  }
  
  function isObject(arg) {
    return typeof arg === 'object' && arg !== null;
  }
  
  function isUndefined(arg) {
    return arg === void 0;
  }
  
  },{}],47:[function(require,module,exports){
  var http = module.exports;
  var EventEmitter = require('events').EventEmitter;
  var Request = require('./lib/request');
  var url = require('url')
  
  http.request = function (params, cb) {
      if (typeof params === 'string') {
          params = url.parse(params)
      }
      if (!params) params = {};
      if (!params.host && !params.port) {
          params.port = parseInt(window.location.port, 10);
      }
      if (!params.host && params.hostname) {
          params.host = params.hostname;
      }
  
      if (!params.protocol) {
          if (params.scheme) {
              params.protocol = params.scheme + ':';
          } else {
              params.protocol = window.location.protocol;
          }
      }
  
      if (!params.host) {
          params.host = window.location.hostname || window.location.host;
      }
      if (/:/.test(params.host)) {
          if (!params.port) {
              params.port = params.host.split(':')[1];
          }
          params.host = params.host.split(':')[0];
      }
      if (!params.port) params.port = params.protocol == 'https:' ? 443 : 80;
      
      var req = new Request(new xhrHttp, params);
      if (cb) req.on('response', cb);
      return req;
  };
  
  http.get = function (params, cb) {
      params.method = 'GET';
      var req = http.request(params, cb);
      req.end();
      return req;
  };
  
  http.Agent = function () {};
  http.Agent.defaultMaxSockets = 4;
  
  var xhrHttp = (function () {
      if (typeof window === 'undefined') {
          throw new Error('no window object present');
      }
      else if (window.XMLHttpRequest) {
          return window.XMLHttpRequest;
      }
      else if (window.ActiveXObject) {
          var axs = [
              'Msxml2.XMLHTTP.6.0',
              'Msxml2.XMLHTTP.3.0',
              'Microsoft.XMLHTTP'
          ];
          for (var i = 0; i < axs.length; i++) {
              try {
                  var ax = new(window.ActiveXObject)(axs[i]);
                  return function () {
                      if (ax) {
                          var ax_ = ax;
                          ax = null;
                          return ax_;
                      }
                      else {
                          return new(window.ActiveXObject)(axs[i]);
                      }
                  };
              }
              catch (e) {}
          }
          throw new Error('ajax not supported in this browser')
      }
      else {
          throw new Error('ajax not supported in this browser');
      }
  })();
  
  http.STATUS_CODES = {
      100 : 'Continue',
      101 : 'Switching Protocols',
      102 : 'Processing',                 // RFC 2518, obsoleted by RFC 4918
      200 : 'OK',
      201 : 'Created',
      202 : 'Accepted',
      203 : 'Non-Authoritative Information',
      204 : 'No Content',
      205 : 'Reset Content',
      206 : 'Partial Content',
      207 : 'Multi-Status',               // RFC 4918
      300 : 'Multiple Choices',
      301 : 'Moved Permanently',
      302 : 'Moved Temporarily',
      303 : 'See Other',
      304 : 'Not Modified',
      305 : 'Use Proxy',
      307 : 'Temporary Redirect',
      400 : 'Bad Request',
      401 : 'Unauthorized',
      402 : 'Payment Required',
      403 : 'Forbidden',
      404 : 'Not Found',
      405 : 'Method Not Allowed',
      406 : 'Not Acceptable',
      407 : 'Proxy Authentication Required',
      408 : 'Request Time-out',
      409 : 'Conflict',
      410 : 'Gone',
      411 : 'Length Required',
      412 : 'Precondition Failed',
      413 : 'Request Entity Too Large',
      414 : 'Request-URI Too Large',
      415 : 'Unsupported Media Type',
      416 : 'Requested Range Not Satisfiable',
      417 : 'Expectation Failed',
      418 : 'I\'m a teapot',              // RFC 2324
      422 : 'Unprocessable Entity',       // RFC 4918
      423 : 'Locked',                     // RFC 4918
      424 : 'Failed Dependency',          // RFC 4918
      425 : 'Unordered Collection',       // RFC 4918
      426 : 'Upgrade Required',           // RFC 2817
      428 : 'Precondition Required',      // RFC 6585
      429 : 'Too Many Requests',          // RFC 6585
      431 : 'Request Header Fields Too Large',// RFC 6585
      500 : 'Internal Server Error',
      501 : 'Not Implemented',
      502 : 'Bad Gateway',
      503 : 'Service Unavailable',
      504 : 'Gateway Time-out',
      505 : 'HTTP Version Not Supported',
      506 : 'Variant Also Negotiates',    // RFC 2295
      507 : 'Insufficient Storage',       // RFC 4918
      509 : 'Bandwidth Limit Exceeded',
      510 : 'Not Extended',               // RFC 2774
      511 : 'Network Authentication Required' // RFC 6585
  };
  },{"./lib/request":48,"events":46,"url":72}],48:[function(require,module,exports){
  var Stream = require('stream');
  var Response = require('./response');
  var Base64 = require('Base64');
  var inherits = require('inherits');
  
  var Request = module.exports = function (xhr, params) {
      var self = this;
      self.writable = true;
      self.xhr = xhr;
      self.body = [];
      
      self.uri = (params.protocol || 'http:') + '//'
          + params.host
          + (params.port ? ':' + params.port : '')
          + (params.path || '/')
      ;
      
      if (typeof params.withCredentials === 'undefined') {
          params.withCredentials = true;
      }
  
      try { xhr.withCredentials = params.withCredentials }
      catch (e) {}
      
      if (params.responseType) try { xhr.responseType = params.responseType }
      catch (e) {}
      
      xhr.open(
          params.method || 'GET',
          self.uri,
          true
      );
  
      xhr.onerror = function(event) {
          self.emit('error', new Error('Network error'));
      };
  
      self._headers = {};
      
      if (params.headers) {
          var keys = objectKeys(params.headers);
          for (var i = 0; i < keys.length; i++) {
              var key = keys[i];
              if (!self.isSafeRequestHeader(key)) continue;
              var value = params.headers[key];
              self.setHeader(key, value);
          }
      }
      
      if (params.auth) {
          //basic auth
          this.setHeader('Authorization', 'Basic ' + Base64.btoa(params.auth));
      }
  
      var res = new Response;
      res.on('close', function () {
          self.emit('close');
      });
      
      res.on('ready', function () {
          self.emit('response', res);
      });
  
      res.on('error', function (err) {
          self.emit('error', err);
      });
      
      xhr.onreadystatechange = function () {
          // Fix for IE9 bug
          // SCRIPT575: Could not complete the operation due to error c00c023f
          // It happens when a request is aborted, calling the success callback anyway with readyState === 4
          if (xhr.__aborted) return;
          res.handle(xhr);
      };
  };
  
  inherits(Request, Stream);
  
  Request.prototype.setHeader = function (key, value) {
      this._headers[key.toLowerCase()] = value
  };
  
  Request.prototype.getHeader = function (key) {
      return this._headers[key.toLowerCase()]
  };
  
  Request.prototype.removeHeader = function (key) {
      delete this._headers[key.toLowerCase()]
  };
  
  Request.prototype.write = function (s) {
      this.body.push(s);
  };
  
  Request.prototype.destroy = function (s) {
      this.xhr.__aborted = true;
      this.xhr.abort();
      this.emit('close');
  };
  
  Request.prototype.end = function (s) {
      if (s !== undefined) this.body.push(s);
  
      var keys = objectKeys(this._headers);
      for (var i = 0; i < keys.length; i++) {
          var key = keys[i];
          var value = this._headers[key];
          if (isArray(value)) {
              for (var j = 0; j < value.length; j++) {
                  this.xhr.setRequestHeader(key, value[j]);
              }
          }
          else this.xhr.setRequestHeader(key, value)
      }
  
      if (this.body.length === 0) {
          this.xhr.send('');
      }
      else if (typeof this.body[0] === 'string') {
          this.xhr.send(this.body.join(''));
      }
      else if (isArray(this.body[0])) {
          var body = [];
          for (var i = 0; i < this.body.length; i++) {
              body.push.apply(body, this.body[i]);
          }
          this.xhr.send(body);
      }
      else if (/Array/.test(Object.prototype.toString.call(this.body[0]))) {
          var len = 0;
          for (var i = 0; i < this.body.length; i++) {
              len += this.body[i].length;
          }
          var body = new(this.body[0].constructor)(len);
          var k = 0;
          
          for (var i = 0; i < this.body.length; i++) {
              var b = this.body[i];
              for (var j = 0; j < b.length; j++) {
                  body[k++] = b[j];
              }
          }
          this.xhr.send(body);
      }
      else if (isXHR2Compatible(this.body[0])) {
          this.xhr.send(this.body[0]);
      }
      else {
          var body = '';
          for (var i = 0; i < this.body.length; i++) {
              body += this.body[i].toString();
          }
          this.xhr.send(body);
      }
  };
  
  // Taken from http://dxr.mozilla.org/mozilla/mozilla-central/content/base/src/nsXMLHttpRequest.cpp.html
  Request.unsafeHeaders = [
      "accept-charset",
      "accept-encoding",
      "access-control-request-headers",
      "access-control-request-method",
      "connection",
      "content-length",
      "cookie",
      "cookie2",
      "content-transfer-encoding",
      "date",
      "expect",
      "host",
      "keep-alive",
      "origin",
      "referer",
      "te",
      "trailer",
      "transfer-encoding",
      "upgrade",
      "user-agent",
      "via"
  ];
  
  Request.prototype.isSafeRequestHeader = function (headerName) {
      if (!headerName) return false;
      return indexOf(Request.unsafeHeaders, headerName.toLowerCase()) === -1;
  };
  
  var objectKeys = Object.keys || function (obj) {
      var keys = [];
      for (var key in obj) keys.push(key);
      return keys;
  };
  
  var isArray = Array.isArray || function (xs) {
      return Object.prototype.toString.call(xs) === '[object Array]';
  };
  
  var indexOf = function (xs, x) {
      if (xs.indexOf) return xs.indexOf(x);
      for (var i = 0; i < xs.length; i++) {
          if (xs[i] === x) return i;
      }
      return -1;
  };
  
  var isXHR2Compatible = function (obj) {
      if (typeof Blob !== 'undefined' && obj instanceof Blob) return true;
      if (typeof ArrayBuffer !== 'undefined' && obj instanceof ArrayBuffer) return true;
      if (typeof FormData !== 'undefined' && obj instanceof FormData) return true;
  };
  
  },{"./response":49,"Base64":50,"inherits":52,"stream":70}],49:[function(require,module,exports){
  var Stream = require('stream');
  var util = require('util');
  
  var Response = module.exports = function (res) {
      this.offset = 0;
      this.readable = true;
  };
  
  util.inherits(Response, Stream);
  
  var capable = {
      streaming : true,
      status2 : true
  };
  
  function parseHeaders (res) {
      var lines = res.getAllResponseHeaders().split(/\r?\n/);
      var headers = {};
      for (var i = 0; i < lines.length; i++) {
          var line = lines[i];
          if (line === '') continue;
          
          var m = line.match(/^([^:]+):\s*(.*)/);
          if (m) {
              var key = m[1].toLowerCase(), value = m[2];
              
              if (headers[key] !== undefined) {
              
                  if (isArray(headers[key])) {
                      headers[key].push(value);
                  }
                  else {
                      headers[key] = [ headers[key], value ];
                  }
              }
              else {
                  headers[key] = value;
              }
          }
          else {
              headers[line] = true;
          }
      }
      return headers;
  }
  
  Response.prototype.getResponse = function (xhr) {
      var respType = String(xhr.responseType).toLowerCase();
      if (respType === 'blob') return xhr.responseBlob || xhr.response;
      if (respType === 'arraybuffer') return xhr.response;
      return xhr.responseText;
  }
  
  Response.prototype.getHeader = function (key) {
      return this.headers[key.toLowerCase()];
  };
  
  Response.prototype.handle = function (res) {
      if (res.readyState === 2 && capable.status2) {
          try {
              this.statusCode = res.status;
              this.headers = parseHeaders(res);
          }
          catch (err) {
              capable.status2 = false;
          }
          
          if (capable.status2) {
              this.emit('ready');
          }
      }
      else if (capable.streaming && res.readyState === 3) {
          try {
              if (!this.statusCode) {
                  this.statusCode = res.status;
                  this.headers = parseHeaders(res);
                  this.emit('ready');
              }
          }
          catch (err) {}
          
          try {
              this._emitData(res);
          }
          catch (err) {
              capable.streaming = false;
          }
      }
      else if (res.readyState === 4) {
          if (!this.statusCode) {
              this.statusCode = res.status;
              this.emit('ready');
          }
          this._emitData(res);
          
          if (res.error) {
              this.emit('error', this.getResponse(res));
          }
          else this.emit('end');
          
          this.emit('close');
      }
  };
  
  Response.prototype._emitData = function (res) {
      var respBody = this.getResponse(res);
      if (respBody.toString().match(/ArrayBuffer/)) {
          this.emit('data', new Uint8Array(respBody, this.offset));
          this.offset = respBody.byteLength;
          return;
      }
      if (respBody.length > this.offset) {
          this.emit('data', respBody.slice(this.offset));
          this.offset = respBody.length;
      }
  };
  
  var isArray = Array.isArray || function (xs) {
      return Object.prototype.toString.call(xs) === '[object Array]';
  };
  
  },{"stream":70,"util":74}],50:[function(require,module,exports){
  ;(function () {
  
    var object = typeof exports != 'undefined' ? exports : this; // #8: web workers
    var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
  
    function InvalidCharacterError(message) {
      this.message = message;
    }
    InvalidCharacterError.prototype = new Error;
    InvalidCharacterError.prototype.name = 'InvalidCharacterError';
  
    // encoder
    // [https://gist.github.com/999166] by [https://github.com/nignag]
    object.btoa || (
    object.btoa = function (input) {
      for (
        // initialize result and counter
        var block, charCode, idx = 0, map = chars, output = '';
        // if the next input index does not exist:
        //   change the mapping table to "="
        //   check if d has no fractional digits
        input.charAt(idx | 0) || (map = '=', idx % 1);
        // "8 - idx % 1 * 8" generates the sequence 2, 4, 6, 8
        output += map.charAt(63 & block >> 8 - idx % 1 * 8)
      ) {
        charCode = input.charCodeAt(idx += 3/4);
        if (charCode > 0xFF) {
          throw new InvalidCharacterError("'btoa' failed: The string to be encoded contains characters outside of the Latin1 range.");
        }
        block = block << 8 | charCode;
      }
      return output;
    });
  
    // decoder
    // [https://gist.github.com/1020396] by [https://github.com/atk]
    object.atob || (
    object.atob = function (input) {
      input = input.replace(/=+$/, '');
      if (input.length % 4 == 1) {
        throw new InvalidCharacterError("'atob' failed: The string to be decoded is not correctly encoded.");
      }
      for (
        // initialize result and counters
        var bc = 0, bs, buffer, idx = 0, output = '';
        // get next character
        buffer = input.charAt(idx++);
        // character found in table? initialize bit storage and add its ascii value;
        ~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer,
          // and if not first of each 4 characters,
          // convert the first 8 bits to one ascii character
          bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0
      ) {
        // try to find character in table (0-63, not found => -1)
        buffer = chars.indexOf(buffer);
      }
      return output;
    });
  
  }());
  
  },{}],51:[function(require,module,exports){
  var http = require('http');
  
  var https = module.exports;
  
  for (var key in http) {
      if (http.hasOwnProperty(key)) https[key] = http[key];
  };
  
  https.request = function (params, cb) {
      if (!params) params = {};
      params.scheme = 'https';
      return http.request.call(this, params, cb);
  }
  
  },{"http":47}],52:[function(require,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
    }
  }
  
  },{}],53:[function(require,module,exports){
  module.exports = Array.isArray || function (arr) {
    return Object.prototype.toString.call(arr) == '[object Array]';
  };
  
  },{}],54:[function(require,module,exports){
  // shim for using process in browser
  
  var process = module.exports = {};
  var queue = [];
  var draining = false;
  
  function drainQueue() {
      if (draining) {
          return;
      }
      draining = true;
      var currentQueue;
      var len = queue.length;
      while(len) {
          currentQueue = queue;
          queue = [];
          var i = -1;
          while (++i < len) {
              currentQueue[i]();
          }
          len = queue.length;
      }
      draining = false;
  }
  process.nextTick = function (fun) {
      queue.push(fun);
      if (!draining) {
          setTimeout(drainQueue, 0);
      }
  };
  
  process.title = 'browser';
  process.browser = true;
  process.env = {};
  process.argv = [];
  process.version = ''; // empty string to avoid regexp issues
  
  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');
  };
  process.umask = function() { return 0; };
  
  },{}],55:[function(require,module,exports){
  (function (global){
  /*! http://mths.be/punycode v1.2.4 by @mathias */
  ;(function(root) {
  
  	/** Detect free variables */
  	var freeExports = typeof exports == 'object' && exports;
  	var freeModule = typeof module == 'object' && module &&
  		module.exports == freeExports && module;
  	var freeGlobal = typeof global == 'object' && global;
  	if (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal) {
  		root = freeGlobal;
  	}
  
  	/**
  	 * The `punycode` object.
  	 * @name punycode
  	 * @type Object
  	 */
  	var punycode,
  
  	/** Highest positive signed 32-bit float value */
  	maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1
  
  	/** Bootstring parameters */
  	base = 36,
  	tMin = 1,
  	tMax = 26,
  	skew = 38,
  	damp = 700,
  	initialBias = 72,
  	initialN = 128, // 0x80
  	delimiter = '-', // '\x2D'
  
  	/** Regular expressions */
  	regexPunycode = /^xn--/,
  	regexNonASCII = /[^ -~]/, // unprintable ASCII chars + non-ASCII chars
  	regexSeparators = /\x2E|\u3002|\uFF0E|\uFF61/g, // RFC 3490 separators
  
  	/** Error messages */
  	errors = {
  		'overflow': 'Overflow: input needs wider integers to process',
  		'not-basic': 'Illegal input >= 0x80 (not a basic code point)',
  		'invalid-input': 'Invalid input'
  	},
  
  	/** Convenience shortcuts */
  	baseMinusTMin = base - tMin,
  	floor = Math.floor,
  	stringFromCharCode = String.fromCharCode,
  
  	/** Temporary variable */
  	key;
  
  	/*--------------------------------------------------------------------------*/
  
  	/**
  	 * A generic error utility function.
  	 * @private
  	 * @param {String} type The error type.
  	 * @returns {Error} Throws a `RangeError` with the applicable error message.
  	 */
  	function error(type) {
  		throw RangeError(errors[type]);
  	}
  
  	/**
  	 * A generic `Array#map` utility function.
  	 * @private
  	 * @param {Array} array The array to iterate over.
  	 * @param {Function} callback The function that gets called for every array
  	 * item.
  	 * @returns {Array} A new array of values returned by the callback function.
  	 */
  	function map(array, fn) {
  		var length = array.length;
  		while (length--) {
  			array[length] = fn(array[length]);
  		}
  		return array;
  	}
  
  	/**
  	 * A simple `Array#map`-like wrapper to work with domain name strings.
  	 * @private
  	 * @param {String} domain The domain name.
  	 * @param {Function} callback The function that gets called for every
  	 * character.
  	 * @returns {Array} A new string of characters returned by the callback
  	 * function.
  	 */
  	function mapDomain(string, fn) {
  		return map(string.split(regexSeparators), fn).join('.');
  	}
  
  	/**
  	 * Creates an array containing the numeric code points of each Unicode
  	 * character in the string. While JavaScript uses UCS-2 internally,
  	 * this function will convert a pair of surrogate halves (each of which
  	 * UCS-2 exposes as separate characters) into a single code point,
  	 * matching UTF-16.
  	 * @see `punycode.ucs2.encode`
  	 * @see <http://mathiasbynens.be/notes/javascript-encoding>
  	 * @memberOf punycode.ucs2
  	 * @name decode
  	 * @param {String} string The Unicode input string (UCS-2).
  	 * @returns {Array} The new array of code points.
  	 */
  	function ucs2decode(string) {
  		var output = [],
  		    counter = 0,
  		    length = string.length,
  		    value,
  		    extra;
  		while (counter < length) {
  			value = string.charCodeAt(counter++);
  			if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
  				// high surrogate, and there is a next character
  				extra = string.charCodeAt(counter++);
  				if ((extra & 0xFC00) == 0xDC00) { // low surrogate
  					output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
  				} else {
  					// unmatched surrogate; only append this code unit, in case the next
  					// code unit is the high surrogate of a surrogate pair
  					output.push(value);
  					counter--;
  				}
  			} else {
  				output.push(value);
  			}
  		}
  		return output;
  	}
  
  	/**
  	 * Creates a string based on an array of numeric code points.
  	 * @see `punycode.ucs2.decode`
  	 * @memberOf punycode.ucs2
  	 * @name encode
  	 * @param {Array} codePoints The array of numeric code points.
  	 * @returns {String} The new Unicode string (UCS-2).
  	 */
  	function ucs2encode(array) {
  		return map(array, function(value) {
  			var output = '';
  			if (value > 0xFFFF) {
  				value -= 0x10000;
  				output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
  				value = 0xDC00 | value & 0x3FF;
  			}
  			output += stringFromCharCode(value);
  			return output;
  		}).join('');
  	}
  
  	/**
  	 * Converts a basic code point into a digit/integer.
  	 * @see `digitToBasic()`
  	 * @private
  	 * @param {Number} codePoint The basic numeric code point value.
  	 * @returns {Number} The numeric value of a basic code point (for use in
  	 * representing integers) in the range `0` to `base - 1`, or `base` if
  	 * the code point does not represent a value.
  	 */
  	function basicToDigit(codePoint) {
  		if (codePoint - 48 < 10) {
  			return codePoint - 22;
  		}
  		if (codePoint - 65 < 26) {
  			return codePoint - 65;
  		}
  		if (codePoint - 97 < 26) {
  			return codePoint - 97;
  		}
  		return base;
  	}
  
  	/**
  	 * Converts a digit/integer into a basic code point.
  	 * @see `basicToDigit()`
  	 * @private
  	 * @param {Number} digit The numeric value of a basic code point.
  	 * @returns {Number} The basic code point whose value (when used for
  	 * representing integers) is `digit`, which needs to be in the range
  	 * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is
  	 * used; else, the lowercase form is used. The behavior is undefined
  	 * if `flag` is non-zero and `digit` has no uppercase form.
  	 */
  	function digitToBasic(digit, flag) {
  		//  0..25 map to ASCII a..z or A..Z
  		// 26..35 map to ASCII 0..9
  		return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
  	}
  
  	/**
  	 * Bias adaptation function as per section 3.4 of RFC 3492.
  	 * http://tools.ietf.org/html/rfc3492#section-3.4
  	 * @private
  	 */
  	function adapt(delta, numPoints, firstTime) {
  		var k = 0;
  		delta = firstTime ? floor(delta / damp) : delta >> 1;
  		delta += floor(delta / numPoints);
  		for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) {
  			delta = floor(delta / baseMinusTMin);
  		}
  		return floor(k + (baseMinusTMin + 1) * delta / (delta + skew));
  	}
  
  	/**
  	 * Converts a Punycode string of ASCII-only symbols to a string of Unicode
  	 * symbols.
  	 * @memberOf punycode
  	 * @param {String} input The Punycode string of ASCII-only symbols.
  	 * @returns {String} The resulting string of Unicode symbols.
  	 */
  	function decode(input) {
  		// Don't use UCS-2
  		var output = [],
  		    inputLength = input.length,
  		    out,
  		    i = 0,
  		    n = initialN,
  		    bias = initialBias,
  		    basic,
  		    j,
  		    index,
  		    oldi,
  		    w,
  		    k,
  		    digit,
  		    t,
  		    /** Cached calculation results */
  		    baseMinusT;
  
  		// Handle the basic code points: let `basic` be the number of input code
  		// points before the last delimiter, or `0` if there is none, then copy
  		// the first basic code points to the output.
  
  		basic = input.lastIndexOf(delimiter);
  		if (basic < 0) {
  			basic = 0;
  		}
  
  		for (j = 0; j < basic; ++j) {
  			// if it's not a basic code point
  			if (input.charCodeAt(j) >= 0x80) {
  				error('not-basic');
  			}
  			output.push(input.charCodeAt(j));
  		}
  
  		// Main decoding loop: start just after the last delimiter if any basic code
  		// points were copied; start at the beginning otherwise.
  
  		for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) {
  
  			// `index` is the index of the next character to be consumed.
  			// Decode a generalized variable-length integer into `delta`,
  			// which gets added to `i`. The overflow checking is easier
  			// if we increase `i` as we go, then subtract off its starting
  			// value at the end to obtain `delta`.
  			for (oldi = i, w = 1, k = base; /* no condition */; k += base) {
  
  				if (index >= inputLength) {
  					error('invalid-input');
  				}
  
  				digit = basicToDigit(input.charCodeAt(index++));
  
  				if (digit >= base || digit > floor((maxInt - i) / w)) {
  					error('overflow');
  				}
  
  				i += digit * w;
  				t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
  
  				if (digit < t) {
  					break;
  				}
  
  				baseMinusT = base - t;
  				if (w > floor(maxInt / baseMinusT)) {
  					error('overflow');
  				}
  
  				w *= baseMinusT;
  
  			}
  
  			out = output.length + 1;
  			bias = adapt(i - oldi, out, oldi == 0);
  
  			// `i` was supposed to wrap around from `out` to `0`,
  			// incrementing `n` each time, so we'll fix that now:
  			if (floor(i / out) > maxInt - n) {
  				error('overflow');
  			}
  
  			n += floor(i / out);
  			i %= out;
  
  			// Insert `n` at position `i` of the output
  			output.splice(i++, 0, n);
  
  		}
  
  		return ucs2encode(output);
  	}
  
  	/**
  	 * Converts a string of Unicode symbols to a Punycode string of ASCII-only
  	 * symbols.
  	 * @memberOf punycode
  	 * @param {String} input The string of Unicode symbols.
  	 * @returns {String} The resulting Punycode string of ASCII-only symbols.
  	 */
  	function encode(input) {
  		var n,
  		    delta,
  		    handledCPCount,
  		    basicLength,
  		    bias,
  		    j,
  		    m,
  		    q,
  		    k,
  		    t,
  		    currentValue,
  		    output = [],
  		    /** `inputLength` will hold the number of code points in `input`. */
  		    inputLength,
  		    /** Cached calculation results */
  		    handledCPCountPlusOne,
  		    baseMinusT,
  		    qMinusT;
  
  		// Convert the input in UCS-2 to Unicode
  		input = ucs2decode(input);
  
  		// Cache the length
  		inputLength = input.length;
  
  		// Initialize the state
  		n = initialN;
  		delta = 0;
  		bias = initialBias;
  
  		// Handle the basic code points
  		for (j = 0; j < inputLength; ++j) {
  			currentValue = input[j];
  			if (currentValue < 0x80) {
  				output.push(stringFromCharCode(currentValue));
  			}
  		}
  
  		handledCPCount = basicLength = output.length;
  
  		// `handledCPCount` is the number of code points that have been handled;
  		// `basicLength` is the number of basic code points.
  
  		// Finish the basic string - if it is not empty - with a delimiter
  		if (basicLength) {
  			output.push(delimiter);
  		}
  
  		// Main encoding loop:
  		while (handledCPCount < inputLength) {
  
  			// All non-basic code points < n have been handled already. Find the next
  			// larger one:
  			for (m = maxInt, j = 0; j < inputLength; ++j) {
  				currentValue = input[j];
  				if (currentValue >= n && currentValue < m) {
  					m = currentValue;
  				}
  			}
  
  			// Increase `delta` enough to advance the decoder's <n,i> state to <m,0>,
  			// but guard against overflow
  			handledCPCountPlusOne = handledCPCount + 1;
  			if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {
  				error('overflow');
  			}
  
  			delta += (m - n) * handledCPCountPlusOne;
  			n = m;
  
  			for (j = 0; j < inputLength; ++j) {
  				currentValue = input[j];
  
  				if (currentValue < n && ++delta > maxInt) {
  					error('overflow');
  				}
  
  				if (currentValue == n) {
  					// Represent delta as a generalized variable-length integer
  					for (q = delta, k = base; /* no condition */; k += base) {
  						t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
  						if (q < t) {
  							break;
  						}
  						qMinusT = q - t;
  						baseMinusT = base - t;
  						output.push(
  							stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))
  						);
  						q = floor(qMinusT / baseMinusT);
  					}
  
  					output.push(stringFromCharCode(digitToBasic(q, 0)));
  					bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);
  					delta = 0;
  					++handledCPCount;
  				}
  			}
  
  			++delta;
  			++n;
  
  		}
  		return output.join('');
  	}
  
  	/**
  	 * Converts a Punycode string representing a domain name to Unicode. Only the
  	 * Punycoded parts of the domain name will be converted, i.e. it doesn't
  	 * matter if you call it on a string that has already been converted to
  	 * Unicode.
  	 * @memberOf punycode
  	 * @param {String} domain The Punycode domain name to convert to Unicode.
  	 * @returns {String} The Unicode representation of the given Punycode
  	 * string.
  	 */
  	function toUnicode(domain) {
  		return mapDomain(domain, function(string) {
  			return regexPunycode.test(string)
  				? decode(string.slice(4).toLowerCase())
  				: string;
  		});
  	}
  
  	/**
  	 * Converts a Unicode string representing a domain name to Punycode. Only the
  	 * non-ASCII parts of the domain name will be converted, i.e. it doesn't
  	 * matter if you call it with a domain that's already in ASCII.
  	 * @memberOf punycode
  	 * @param {String} domain The domain name to convert, as a Unicode string.
  	 * @returns {String} The Punycode representation of the given domain name.
  	 */
  	function toASCII(domain) {
  		return mapDomain(domain, function(string) {
  			return regexNonASCII.test(string)
  				? 'xn--' + encode(string)
  				: string;
  		});
  	}
  
  	/*--------------------------------------------------------------------------*/
  
  	/** Define the public API */
  	punycode = {
  		/**
  		 * A string representing the current Punycode.js version number.
  		 * @memberOf punycode
  		 * @type String
  		 */
  		'version': '1.2.4',
  		/**
  		 * An object of methods to convert from JavaScript's internal character
  		 * representation (UCS-2) to Unicode code points, and back.
  		 * @see <http://mathiasbynens.be/notes/javascript-encoding>
  		 * @memberOf punycode
  		 * @type Object
  		 */
  		'ucs2': {
  			'decode': ucs2decode,
  			'encode': ucs2encode
  		},
  		'decode': decode,
  		'encode': encode,
  		'toASCII': toASCII,
  		'toUnicode': toUnicode
  	};
  
  	/** Expose `punycode` */
  	// Some AMD build optimizers, like r.js, check for specific condition patterns
  	// like the following:
  	if (
  		typeof define == 'function' &&
  		typeof define.amd == 'object' &&
  		define.amd
  	) {
  		define('punycode', function() {
  			return punycode;
  		});
  	} else if (freeExports && !freeExports.nodeType) {
  		if (freeModule) { // in Node.js or RingoJS v0.8.0+
  			freeModule.exports = punycode;
  		} else { // in Narwhal or RingoJS v0.7.0-
  			for (key in punycode) {
  				punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]);
  			}
  		}
  	} else { // in Rhino or a web browser
  		root.punycode = punycode;
  	}
  
  }(this));
  
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  },{}],56:[function(require,module,exports){
  // 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.
  
  'use strict';
  
  // If obj.hasOwnProperty has been overridden, then calling
  // obj.hasOwnProperty(prop) will break.
  // See: https://github.com/joyent/node/issues/1707
  function hasOwnProperty(obj, prop) {
    return Object.prototype.hasOwnProperty.call(obj, prop);
  }
  
  module.exports = function(qs, sep, eq, options) {
    sep = sep || '&';
    eq = eq || '=';
    var obj = {};
  
    if (typeof qs !== 'string' || qs.length === 0) {
      return obj;
    }
  
    var regexp = /\+/g;
    qs = qs.split(sep);
  
    var maxKeys = 1000;
    if (options && typeof options.maxKeys === 'number') {
      maxKeys = options.maxKeys;
    }
  
    var len = qs.length;
    // maxKeys <= 0 means that we should not limit keys count
    if (maxKeys > 0 && len > maxKeys) {
      len = maxKeys;
    }
  
    for (var i = 0; i < len; ++i) {
      var x = qs[i].replace(regexp, '%20'),
          idx = x.indexOf(eq),
          kstr, vstr, k, v;
  
      if (idx >= 0) {
        kstr = x.substr(0, idx);
        vstr = x.substr(idx + 1);
      } else {
        kstr = x;
        vstr = '';
      }
  
      k = decodeURIComponent(kstr);
      v = decodeURIComponent(vstr);
  
      if (!hasOwnProperty(obj, k)) {
        obj[k] = v;
      } else if (isArray(obj[k])) {
        obj[k].push(v);
      } else {
        obj[k] = [obj[k], v];
      }
    }
  
    return obj;
  };
  
  var isArray = Array.isArray || function (xs) {
    return Object.prototype.toString.call(xs) === '[object Array]';
  };
  
  },{}],57:[function(require,module,exports){
  // 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.
  
  'use strict';
  
  var stringifyPrimitive = function(v) {
    switch (typeof v) {
      case 'string':
        return v;
  
      case 'boolean':
        return v ? 'true' : 'false';
  
      case 'number':
        return isFinite(v) ? v : '';
  
      default:
        return '';
    }
  };
  
  module.exports = function(obj, sep, eq, name) {
    sep = sep || '&';
    eq = eq || '=';
    if (obj === null) {
      obj = undefined;
    }
  
    if (typeof obj === 'object') {
      return map(objectKeys(obj), function(k) {
        var ks = encodeURIComponent(stringifyPrimitive(k)) + eq;
        if (isArray(obj[k])) {
          return map(obj[k], function(v) {
            return ks + encodeURIComponent(stringifyPrimitive(v));
          }).join(sep);
        } else {
          return ks + encodeURIComponent(stringifyPrimitive(obj[k]));
        }
      }).join(sep);
  
    }
  
    if (!name) return '';
    return encodeURIComponent(stringifyPrimitive(name)) + eq +
           encodeURIComponent(stringifyPrimitive(obj));
  };
  
  var isArray = Array.isArray || function (xs) {
    return Object.prototype.toString.call(xs) === '[object Array]';
  };
  
  function map (xs, f) {
    if (xs.map) return xs.map(f);
    var res = [];
    for (var i = 0; i < xs.length; i++) {
      res.push(f(xs[i], i));
    }
    return res;
  }
  
  var objectKeys = Object.keys || function (obj) {
    var res = [];
    for (var key in obj) {
      if (Object.prototype.hasOwnProperty.call(obj, key)) res.push(key);
    }
    return res;
  };
  
  },{}],58:[function(require,module,exports){
  'use strict';
  
  exports.decode = exports.parse = require('./decode');
  exports.encode = exports.stringify = require('./encode');
  
  },{"./decode":56,"./encode":57}],59:[function(require,module,exports){
  module.exports = require("./lib/_stream_duplex.js")
  
  },{"./lib/_stream_duplex.js":60}],60:[function(require,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.
  
  // a duplex stream is just a stream that is both readable and writable.
  // Since JS doesn't have multiple prototypal inheritance, this class
  // prototypally inherits from Readable, and then parasitically from
  // Writable.
  
  module.exports = Duplex;
  
  /*<replacement>*/
  var objectKeys = Object.keys || function (obj) {
    var keys = [];
    for (var key in obj) keys.push(key);
    return keys;
  }
  /*</replacement>*/
  
  
  /*<replacement>*/
  var util = require('core-util-is');
  util.inherits = require('inherits');
  /*</replacement>*/
  
  var Readable = require('./_stream_readable');
  var Writable = require('./_stream_writable');
  
  util.inherits(Duplex, Readable);
  
  forEach(objectKeys(Writable.prototype), function(method) {
    if (!Duplex.prototype[method])
      Duplex.prototype[method] = Writable.prototype[method];
  });
  
  function Duplex(options) {
    if (!(this instanceof Duplex))
      return new Duplex(options);
  
    Readable.call(this, options);
    Writable.call(this, options);
  
    if (options && options.readable === false)
      this.readable = false;
  
    if (options && options.writable === false)
      this.writable = false;
  
    this.allowHalfOpen = true;
    if (options && options.allowHalfOpen === false)
      this.allowHalfOpen = false;
  
    this.once('end', onend);
  }
  
  // the no-half-open enforcer
  function onend() {
    // if we allow half-open state, or if the writable side ended,
    // then we're ok.
    if (this.allowHalfOpen || this._writableState.ended)
      return;
  
    // no more data can be written.
    // But allow more writes to happen in this tick.
    process.nextTick(this.end.bind(this));
  }
  
  function forEach (xs, f) {
    for (var i = 0, l = xs.length; i < l; i++) {
      f(xs[i], i);
    }
  }
  
  }).call(this,require('_process'))
  },{"./_stream_readable":62,"./_stream_writable":64,"_process":54,"core-util-is":65,"inherits":52}],61:[function(require,module,exports){
  // 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.
  
  // a passthrough stream.
  // basically just the most minimal sort of Transform stream.
  // Every written chunk gets output as-is.
  
  module.exports = PassThrough;
  
  var Transform = require('./_stream_transform');
  
  /*<replacement>*/
  var util = require('core-util-is');
  util.inherits = require('inherits');
  /*</replacement>*/
  
  util.inherits(PassThrough, Transform);
  
  function PassThrough(options) {
    if (!(this instanceof PassThrough))
      return new PassThrough(options);
  
    Transform.call(this, options);
  }
  
  PassThrough.prototype._transform = function(chunk, encoding, cb) {
    cb(null, chunk);
  };
  
  },{"./_stream_transform":63,"core-util-is":65,"inherits":52}],62:[function(require,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.
  
  module.exports = Readable;
  
  /*<replacement>*/
  var isArray = require('isarray');
  /*</replacement>*/
  
  
  /*<replacement>*/
  var Buffer = require('buffer').Buffer;
  /*</replacement>*/
  
  Readable.ReadableState = ReadableState;
  
  var EE = require('events').EventEmitter;
  
  /*<replacement>*/
  if (!EE.listenerCount) EE.listenerCount = function(emitter, type) {
    return emitter.listeners(type).length;
  };
  /*</replacement>*/
  
  var Stream = require('stream');
  
  /*<replacement>*/
  var util = require('core-util-is');
  util.inherits = require('inherits');
  /*</replacement>*/
  
  var StringDecoder;
  
  util.inherits(Readable, Stream);
  
  function ReadableState(options, stream) {
    options = options || {};
  
    // the point at which it stops calling _read() to fill the buffer
    // Note: 0 is a valid value, means "don't call _read preemptively ever"
    var hwm = options.highWaterMark;
    this.highWaterMark = (hwm || hwm === 0) ? hwm : 16 * 1024;
  
    // cast to ints.
    this.highWaterMark = ~~this.highWaterMark;
  
    this.buffer = [];
    this.length = 0;
    this.pipes = null;
    this.pipesCount = 0;
    this.flowing = false;
    this.ended = false;
    this.endEmitted = false;
    this.reading = false;
  
    // In streams that never have any data, and do push(null) right away,
    // the consumer can miss the 'end' event if they do some I/O before
    // consuming the stream.  So, we don't emit('end') until some reading
    // happens.
    this.calledRead = false;
  
    // a flag to be able to tell if the onwrite cb is called immediately,
    // or on a later tick.  We set this to true at first, becuase any
    // actions that shouldn't happen until "later" should generally also
    // not happen before the first write call.
    this.sync = true;
  
    // whenever we return null, then we set a flag to say
    // that we're awaiting a 'readable' event emission.
    this.needReadable = false;
    this.emittedReadable = false;
    this.readableListening = false;
  
  
    // object stream flag. Used to make read(n) ignore n and to
    // make all the buffer merging and length checks go away
    this.objectMode = !!options.objectMode;
  
    // Crypto is kind of old and crusty.  Historically, its default string
    // encoding is 'binary' so we have to make this configurable.
    // Everything else in the universe uses 'utf8', though.
    this.defaultEncoding = options.defaultEncoding || 'utf8';
  
    // when piping, we only care about 'readable' events that happen
    // after read()ing all the bytes and not getting any pushback.
    this.ranOut = false;
  
    // the number of writers that are awaiting a drain event in .pipe()s
    this.awaitDrain = 0;
  
    // if true, a maybeReadMore has been scheduled
    this.readingMore = false;
  
    this.decoder = null;
    this.encoding = null;
    if (options.encoding) {
      if (!StringDecoder)
        StringDecoder = require('string_decoder/').StringDecoder;
      this.decoder = new StringDecoder(options.encoding);
      this.encoding = options.encoding;
    }
  }
  
  function Readable(options) {
    if (!(this instanceof Readable))
      return new Readable(options);
  
    this._readableState = new ReadableState(options, this);
  
    // legacy
    this.readable = true;
  
    Stream.call(this);
  }
  
  // Manually shove something into the read() buffer.
  // This returns true if the highWaterMark has not been hit yet,
  // similar to how Writable.write() returns true if you should
  // write() some more.
  Readable.prototype.push = function(chunk, encoding) {
    var state = this._readableState;
  
    if (typeof chunk === 'string' && !state.objectMode) {
      encoding = encoding || state.defaultEncoding;
      if (encoding !== state.encoding) {
        chunk = new Buffer(chunk, encoding);
        encoding = '';
      }
    }
  
    return readableAddChunk(this, state, chunk, encoding, false);
  };
  
  // Unshift should *always* be something directly out of read()
  Readable.prototype.unshift = function(chunk) {
    var state = this._readableState;
    return readableAddChunk(this, state, chunk, '', true);
  };
  
  function readableAddChunk(stream, state, chunk, encoding, addToFront) {
    var er = chunkInvalid(state, chunk);
    if (er) {
      stream.emit('error', er);
    } else if (chunk === null || chunk === undefined) {
      state.reading = false;
      if (!state.ended)
        onEofChunk(stream, state);
    } else if (state.objectMode || chunk && chunk.length > 0) {
      if (state.ended && !addToFront) {
        var e = new Error('stream.push() after EOF');
        stream.emit('error', e);
      } else if (state.endEmitted && addToFront) {
        var e = new Error('stream.unshift() after end event');
        stream.emit('error', e);
      } else {
        if (state.decoder && !addToFront && !encoding)
          chunk = state.decoder.write(chunk);
  
        // update the buffer info.
        state.length += state.objectMode ? 1 : chunk.length;
        if (addToFront) {
          state.buffer.unshift(chunk);
        } else {
          state.reading = false;
          state.buffer.push(chunk);
        }
  
        if (state.needReadable)
          emitReadable(stream);
  
        maybeReadMore(stream, state);
      }
    } else if (!addToFront) {
      state.reading = false;
    }
  
    return needMoreData(state);
  }
  
  
  
  // if it's past the high water mark, we can push in some more.
  // Also, if we have no data yet, we can stand some
  // more bytes.  This is to work around cases where hwm=0,
  // such as the repl.  Also, if the push() triggered a
  // readable event, and the user called read(largeNumber) such that
  // needReadable was set, then we ought to push more, so that another
  // 'readable' event will be triggered.
  function needMoreData(state) {
    return !state.ended &&
           (state.needReadable ||
            state.length < state.highWaterMark ||
            state.length === 0);
  }
  
  // backwards compatibility.
  Readable.prototype.setEncoding = function(enc) {
    if (!StringDecoder)
      StringDecoder = require('string_decoder/').StringDecoder;
    this._readableState.decoder = new StringDecoder(enc);
    this._readableState.encoding = enc;
  };
  
  // Don't raise the hwm > 128MB
  var MAX_HWM = 0x800000;
  function roundUpToNextPowerOf2(n) {
    if (n >= MAX_HWM) {
      n = MAX_HWM;
    } else {
      // Get the next highest power of 2
      n--;
      for (var p = 1; p < 32; p <<= 1) n |= n >> p;
      n++;
    }
    return n;
  }
  
  function howMuchToRead(n, state) {
    if (state.length === 0 && state.ended)
      return 0;
  
    if (state.objectMode)
      return n === 0 ? 0 : 1;
  
    if (n === null || isNaN(n)) {
      // only flow one buffer at a time
      if (state.flowing && state.buffer.length)
        return state.buffer[0].length;
      else
        return state.length;
    }
  
    if (n <= 0)
      return 0;
  
    // If we're asking for more than the target buffer level,
    // then raise the water mark.  Bump up to the next highest
    // power of 2, to prevent increasing it excessively in tiny
    // amounts.
    if (n > state.highWaterMark)
      state.highWaterMark = roundUpToNextPowerOf2(n);
  
    // don't have that much.  return null, unless we've ended.
    if (n > state.length) {
      if (!state.ended) {
        state.needReadable = true;
        return 0;
      } else
        return state.length;
    }
  
    return n;
  }
  
  // you can override either this method, or the async _read(n) below.
  Readable.prototype.read = function(n) {
    var state = this._readableState;
    state.calledRead = true;
    var nOrig = n;
    var ret;
  
    if (typeof n !== 'number' || n > 0)
      state.emittedReadable = false;
  
    // if we're doing read(0) to trigger a readable event, but we
    // already have a bunch of data in the buffer, then just trigger
    // the 'readable' event and move on.
    if (n === 0 &&
        state.needReadable &&
        (state.length >= state.highWaterMark || state.ended)) {
      emitReadable(this);
      return null;
    }
  
    n = howMuchToRead(n, state);
  
    // if we've ended, and we're now clear, then finish it up.
    if (n === 0 && state.ended) {
      ret = null;
  
      // In cases where the decoder did not receive enough data
      // to produce a full chunk, then immediately received an
      // EOF, state.buffer will contain [<Buffer >, <Buffer 00 ...>].
      // howMuchToRead will see this and coerce the amount to
      // read to zero (because it's looking at the length of the
      // first <Buffer > in state.buffer), and we'll end up here.
      //
      // This can only happen via state.decoder -- no other venue
      // exists for pushing a zero-length chunk into state.buffer
      // and triggering this behavior. In this case, we return our
      // remaining data and end the stream, if appropriate.
      if (state.length > 0 && state.decoder) {
        ret = fromList(n, state);
        state.length -= ret.length;
      }
  
      if (state.length === 0)
        endReadable(this);
  
      return ret;
    }
  
    // All the actual chunk generation logic needs to be
    // *below* the call to _read.  The reason is that in certain
    // synthetic stream cases, such as passthrough streams, _read
    // may be a completely synchronous operation which may change
    // the state of the read buffer, providing enough data when
    // before there was *not* enough.
    //
    // So, the steps are:
    // 1. Figure out what the state of things will be after we do
    // a read from the buffer.
    //
    // 2. If that resulting state will trigger a _read, then call _read.
    // Note that this may be asynchronous, or synchronous.  Yes, it is
    // deeply ugly to write APIs this way, but that still doesn't mean
    // that the Readable class should behave improperly, as streams are
    // designed to be sync/async agnostic.
    // Take note if the _read call is sync or async (ie, if the read call
    // has returned yet), so that we know whether or not it's safe to emit
    // 'readable' etc.
    //
    // 3. Actually pull the requested chunks out of the buffer and return.
  
    // if we need a readable event, then we need to do some reading.
    var doRead = state.needReadable;
  
    // if we currently have less than the highWaterMark, then also read some
    if (state.length - n <= state.highWaterMark)
      doRead = true;
  
    // however, if we've ended, then there's no point, and if we're already
    // reading, then it's unnecessary.
    if (state.ended || state.reading)
      doRead = false;
  
    if (doRead) {
      state.reading = true;
      state.sync = true;
      // if the length is currently zero, then we *need* a readable event.
      if (state.length === 0)
        state.needReadable = true;
      // call internal read method
      this._read(state.highWaterMark);
      state.sync = false;
    }
  
    // If _read called its callback synchronously, then `reading`
    // will be false, and we need to re-evaluate how much data we
    // can return to the user.
    if (doRead && !state.reading)
      n = howMuchToRead(nOrig, state);
  
    if (n > 0)
      ret = fromList(n, state);
    else
      ret = null;
  
    if (ret === null) {
      state.needReadable = true;
      n = 0;
    }
  
    state.length -= n;
  
    // If we have nothing in the buffer, then we want to know
    // as soon as we *do* get something into the buffer.
    if (state.length === 0 && !state.ended)
      state.needReadable = true;
  
    // If we happened to read() exactly the remaining amount in the
    // buffer, and the EOF has been seen at this point, then make sure
    // that we emit 'end' on the very next tick.
    if (state.ended && !state.endEmitted && state.length === 0)
      endReadable(this);
  
    return ret;
  };
  
  function chunkInvalid(state, chunk) {
    var er = null;
    if (!Buffer.isBuffer(chunk) &&
        'string' !== typeof chunk &&
        chunk !== null &&
        chunk !== undefined &&
        !state.objectMode) {
      er = new TypeError('Invalid non-string/buffer chunk');
    }
    return er;
  }
  
  
  function onEofChunk(stream, state) {
    if (state.decoder && !state.ended) {
      var chunk = state.decoder.end();
      if (chunk && chunk.length) {
        state.buffer.push(chunk);
        state.length += state.objectMode ? 1 : chunk.length;
      }
    }
    state.ended = true;
  
    // if we've ended and we have some data left, then emit
    // 'readable' now to make sure it gets picked up.
    if (state.length > 0)
      emitReadable(stream);
    else
      endReadable(stream);
  }
  
  // Don't emit readable right away in sync mode, because this can trigger
  // another read() call => stack overflow.  This way, it might trigger
  // a nextTick recursion warning, but that's not so bad.
  function emitReadable(stream) {
    var state = stream._readableState;
    state.needReadable = false;
    if (state.emittedReadable)
      return;
  
    state.emittedReadable = true;
    if (state.sync)
      process.nextTick(function() {
        emitReadable_(stream);
      });
    else
      emitReadable_(stream);
  }
  
  function emitReadable_(stream) {
    stream.emit('readable');
  }
  
  
  // at this point, the user has presumably seen the 'readable' event,
  // and called read() to consume some data.  that may have triggered
  // in turn another _read(n) call, in which case reading = true if
  // it's in progress.
  // However, if we're not ended, or reading, and the length < hwm,
  // then go ahead and try to read some more preemptively.
  function maybeReadMore(stream, state) {
    if (!state.readingMore) {
      state.readingMore = true;
      process.nextTick(function() {
        maybeReadMore_(stream, state);
      });
    }
  }
  
  function maybeReadMore_(stream, state) {
    var len = state.length;
    while (!state.reading && !state.flowing && !state.ended &&
           state.length < state.highWaterMark) {
      stream.read(0);
      if (len === state.length)
        // didn't get any data, stop spinning.
        break;
      else
        len = state.length;
    }
    state.readingMore = false;
  }
  
  // abstract method.  to be overridden in specific implementation classes.
  // call cb(er, data) where data is <= n in length.
  // for virtual (non-string, non-buffer) streams, "length" is somewhat
  // arbitrary, and perhaps not very meaningful.
  Readable.prototype._read = function(n) {
    this.emit('error', new Error('not implemented'));
  };
  
  Readable.prototype.pipe = function(dest, pipeOpts) {
    var src = this;
    var state = this._readableState;
  
    switch (state.pipesCount) {
      case 0:
        state.pipes = dest;
        break;
      case 1:
        state.pipes = [state.pipes, dest];
        break;
      default:
        state.pipes.push(dest);
        break;
    }
    state.pipesCount += 1;
  
    var doEnd = (!pipeOpts || pipeOpts.end !== false) &&
                dest !== process.stdout &&
                dest !== process.stderr;
  
    var endFn = doEnd ? onend : cleanup;
    if (state.endEmitted)
      process.nextTick(endFn);
    else
      src.once('end', endFn);
  
    dest.on('unpipe', onunpipe);
    function onunpipe(readable) {
      if (readable !== src) return;
      cleanup();
    }
  
    function onend() {
      dest.end();
    }
  
    // when the dest drains, it reduces the awaitDrain counter
    // on the source.  This would be more elegant with a .once()
    // handler in flow(), but adding and removing repeatedly is
    // too slow.
    var ondrain = pipeOnDrain(src);
    dest.on('drain', ondrain);
  
    function cleanup() {
      // cleanup event handlers once the pipe is broken
      dest.removeListener('close', onclose);
      dest.removeListener('finish', onfinish);
      dest.removeListener('drain', ondrain);
      dest.removeListener('error', onerror);
      dest.removeListener('unpipe', onunpipe);
      src.removeListener('end', onend);
      src.removeListener('end', cleanup);
  
      // if the reader is waiting for a drain event from this
      // specific writer, then it would cause it to never start
      // flowing again.
      // So, if this is awaiting a drain, then we just call it now.
      // If we don't know, then assume that we are waiting for one.
      if (!dest._writableState || dest._writableState.needDrain)
        ondrain();
    }
  
    // if the dest has an error, then stop piping into it.
    // however, don't suppress the throwing behavior for this.
    function onerror(er) {
      unpipe();
      dest.removeListener('error', onerror);
      if (EE.listenerCount(dest, 'error') === 0)
        dest.emit('error', er);
    }
    // This is a brutally ugly hack to make sure that our error handler
    // is attached before any userland ones.  NEVER DO THIS.
    if (!dest._events || !dest._events.error)
      dest.on('error', onerror);
    else if (isArray(dest._events.error))
      dest._events.error.unshift(onerror);
    else
      dest._events.error = [onerror, dest._events.error];
  
  
  
    // Both close and finish should trigger unpipe, but only once.
    function onclose() {
      dest.removeListener('finish', onfinish);
      unpipe();
    }
    dest.once('close', onclose);
    function onfinish() {
      dest.removeListener('close', onclose);
      unpipe();
    }
    dest.once('finish', onfinish);
  
    function unpipe() {
      src.unpipe(dest);
    }
  
    // tell the dest that it's being piped to
    dest.emit('pipe', src);
  
    // start the flow if it hasn't been started already.
    if (!state.flowing) {
      // the handler that waits for readable events after all
      // the data gets sucked out in flow.
      // This would be easier to follow with a .once() handler
      // in flow(), but that is too slow.
      this.on('readable', pipeOnReadable);
  
      state.flowing = true;
      process.nextTick(function() {
        flow(src);
      });
    }
  
    return dest;
  };
  
  function pipeOnDrain(src) {
    return function() {
      var dest = this;
      var state = src._readableState;
      state.awaitDrain--;
      if (state.awaitDrain === 0)
        flow(src);
    };
  }
  
  function flow(src) {
    var state = src._readableState;
    var chunk;
    state.awaitDrain = 0;
  
    function write(dest, i, list) {
      var written = dest.write(chunk);
      if (false === written) {
        state.awaitDrain++;
      }
    }
  
    while (state.pipesCount && null !== (chunk = src.read())) {
  
      if (state.pipesCount === 1)
        write(state.pipes, 0, null);
      else
        forEach(state.pipes, write);
  
      src.emit('data', chunk);
  
      // if anyone needs a drain, then we have to wait for that.
      if (state.awaitDrain > 0)
        return;
    }
  
    // if every destination was unpiped, either before entering this
    // function, or in the while loop, then stop flowing.
    //
    // NB: This is a pretty rare edge case.
    if (state.pipesCount === 0) {
      state.flowing = false;
  
      // if there were data event listeners added, then switch to old mode.
      if (EE.listenerCount(src, 'data') > 0)
        emitDataEvents(src);
      return;
    }
  
    // at this point, no one needed a drain, so we just ran out of data
    // on the next readable event, start it over again.
    state.ranOut = true;
  }
  
  function pipeOnReadable() {
    if (this._readableState.ranOut) {
      this._readableState.ranOut = false;
      flow(this);
    }
  }
  
  
  Readable.prototype.unpipe = function(dest) {
    var state = this._readableState;
  
    // if we're not piping anywhere, then do nothing.
    if (state.pipesCount === 0)
      return this;
  
    // just one destination.  most common case.
    if (state.pipesCount === 1) {
      // passed in one, but it's not the right one.
      if (dest && dest !== state.pipes)
        return this;
  
      if (!dest)
        dest = state.pipes;
  
      // got a match.
      state.pipes = null;
      state.pipesCount = 0;
      this.removeListener('readable', pipeOnReadable);
      state.flowing = false;
      if (dest)
        dest.emit('unpipe', this);
      return this;
    }
  
    // slow case. multiple pipe destinations.
  
    if (!dest) {
      // remove all.
      var dests = state.pipes;
      var len = state.pipesCount;
      state.pipes = null;
      state.pipesCount = 0;
      this.removeListener('readable', pipeOnReadable);
      state.flowing = false;
  
      for (var i = 0; i < len; i++)
        dests[i].emit('unpipe', this);
      return this;
    }
  
    // try to find the right one.
    var i = indexOf(state.pipes, dest);
    if (i === -1)
      return this;
  
    state.pipes.splice(i, 1);
    state.pipesCount -= 1;
    if (state.pipesCount === 1)
      state.pipes = state.pipes[0];
  
    dest.emit('unpipe', this);
  
    return this;
  };
  
  // set up data events if they are asked for
  // Ensure readable listeners eventually get something
  Readable.prototype.on = function(ev, fn) {
    var res = Stream.prototype.on.call(this, ev, fn);
  
    if (ev === 'data' && !this._readableState.flowing)
      emitDataEvents(this);
  
    if (ev === 'readable' && this.readable) {
      var state = this._readableState;
      if (!state.readableListening) {
        state.readableListening = true;
        state.emittedReadable = false;
        state.needReadable = true;
        if (!state.reading) {
          this.read(0);
        } else if (state.length) {
          emitReadable(this, state);
        }
      }
    }
  
    return res;
  };
  Readable.prototype.addListener = Readable.prototype.on;
  
  // pause() and resume() are remnants of the legacy readable stream API
  // If the user uses them, then switch into old mode.
  Readable.prototype.resume = function() {
    emitDataEvents(this);
    this.read(0);
    this.emit('resume');
  };
  
  Readable.prototype.pause = function() {
    emitDataEvents(this, true);
    this.emit('pause');
  };
  
  function emitDataEvents(stream, startPaused) {
    var state = stream._readableState;
  
    if (state.flowing) {
      // https://github.com/isaacs/readable-stream/issues/16
      throw new Error('Cannot switch to old mode now.');
    }
  
    var paused = startPaused || false;
    var readable = false;
  
    // convert to an old-style stream.
    stream.readable = true;
    stream.pipe = Stream.prototype.pipe;
    stream.on = stream.addListener = Stream.prototype.on;
  
    stream.on('readable', function() {
      readable = true;
  
      var c;
      while (!paused && (null !== (c = stream.read())))
        stream.emit('data', c);
  
      if (c === null) {
        readable = false;
        stream._readableState.needReadable = true;
      }
    });
  
    stream.pause = function() {
      paused = true;
      this.emit('pause');
    };
  
    stream.resume = function() {
      paused = false;
      if (readable)
        process.nextTick(function() {
          stream.emit('readable');
        });
      else
        this.read(0);
      this.emit('resume');
    };
  
    // now make it start, just in case it hadn't already.
    stream.emit('readable');
  }
  
  // wrap an old-style stream as the async data source.
  // This is *not* part of the readable stream interface.
  // It is an ugly unfortunate mess of history.
  Readable.prototype.wrap = function(stream) {
    var state = this._readableState;
    var paused = false;
  
    var self = this;
    stream.on('end', function() {
      if (state.decoder && !state.ended) {
        var chunk = state.decoder.end();
        if (chunk && chunk.length)
          self.push(chunk);
      }
  
      self.push(null);
    });
  
    stream.on('data', function(chunk) {
      if (state.decoder)
        chunk = state.decoder.write(chunk);
  
      // don't skip over falsy values in objectMode
      //if (state.objectMode && util.isNullOrUndefined(chunk))
      if (state.objectMode && (chunk === null || chunk === undefined))
        return;
      else if (!state.objectMode && (!chunk || !chunk.length))
        return;
  
      var ret = self.push(chunk);
      if (!ret) {
        paused = true;
        stream.pause();
      }
    });
  
    // proxy all the other methods.
    // important when wrapping filters and duplexes.
    for (var i in stream) {
      if (typeof stream[i] === 'function' &&
          typeof this[i] === 'undefined') {
        this[i] = function(method) { return function() {
          return stream[method].apply(stream, arguments);
        }}(i);
      }
    }
  
    // proxy certain important events.
    var events = ['error', 'close', 'destroy', 'pause', 'resume'];
    forEach(events, function(ev) {
      stream.on(ev, self.emit.bind(self, ev));
    });
  
    // when we try to consume some more bytes, simply unpause the
    // underlying stream.
    self._read = function(n) {
      if (paused) {
        paused = false;
        stream.resume();
      }
    };
  
    return self;
  };
  
  
  
  // exposed for testing purposes only.
  Readable._fromList = fromList;
  
  // Pluck off n bytes from an array of buffers.
  // Length is the combined lengths of all the buffers in the list.
  function fromList(n, state) {
    var list = state.buffer;
    var length = state.length;
    var stringMode = !!state.decoder;
    var objectMode = !!state.objectMode;
    var ret;
  
    // nothing in the list, definitely empty.
    if (list.length === 0)
      return null;
  
    if (length === 0)
      ret = null;
    else if (objectMode)
      ret = list.shift();
    else if (!n || n >= length) {
      // read it all, truncate the array.
      if (stringMode)
        ret = list.join('');
      else
        ret = Buffer.concat(list, length);
      list.length = 0;
    } else {
      // read just some of it.
      if (n < list[0].length) {
        // just take a part of the first list item.
        // slice is the same for buffers and strings.
        var buf = list[0];
        ret = buf.slice(0, n);
        list[0] = buf.slice(n);
      } else if (n === list[0].length) {
        // first list is a perfect match
        ret = list.shift();
      } else {
        // complex case.
        // we have enough to cover it, but it spans past the first buffer.
        if (stringMode)
          ret = '';
        else
          ret = new Buffer(n);
  
        var c = 0;
        for (var i = 0, l = list.length; i < l && c < n; i++) {
          var buf = list[0];
          var cpy = Math.min(n - c, buf.length);
  
          if (stringMode)
            ret += buf.slice(0, cpy);
          else
            buf.copy(ret, c, 0, cpy);
  
          if (cpy < buf.length)
            list[0] = buf.slice(cpy);
          else
            list.shift();
  
          c += cpy;
        }
      }
    }
  
    return ret;
  }
  
  function endReadable(stream) {
    var state = stream._readableState;
  
    // If we get here before consuming all the bytes, then that is a
    // bug in node.  Should never happen.
    if (state.length > 0)
      throw new Error('endReadable called on non-empty stream');
  
    if (!state.endEmitted && state.calledRead) {
      state.ended = true;
      process.nextTick(function() {
        // Check that we didn't get one last unshift.
        if (!state.endEmitted && state.length === 0) {
          state.endEmitted = true;
          stream.readable = false;
          stream.emit('end');
        }
      });
    }
  }
  
  function forEach (xs, f) {
    for (var i = 0, l = xs.length; i < l; i++) {
      f(xs[i], i);
    }
  }
  
  function indexOf (xs, x) {
    for (var i = 0, l = xs.length; i < l; i++) {
      if (xs[i] === x) return i;
    }
    return -1;
  }
  
  }).call(this,require('_process'))
  },{"_process":54,"buffer":42,"core-util-is":65,"events":46,"inherits":52,"isarray":53,"stream":70,"string_decoder/":71}],63:[function(require,module,exports){
  // 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.
  
  
  // a transform stream is a readable/writable stream where you do
  // something with the data.  Sometimes it's called a "filter",
  // but that's not a great name for it, since that implies a thing where
  // some bits pass through, and others are simply ignored.  (That would
  // be a valid example of a transform, of course.)
  //
  // While the output is causally related to the input, it's not a
  // necessarily symmetric or synchronous transformation.  For example,
  // a zlib stream might take multiple plain-text writes(), and then
  // emit a single compressed chunk some time in the future.
  //
  // Here's how this works:
  //
  // The Transform stream has all the aspects of the readable and writable
  // stream classes.  When you write(chunk), that calls _write(chunk,cb)
  // internally, and returns false if there's a lot of pending writes
  // buffered up.  When you call read(), that calls _read(n) until
  // there's enough pending readable data buffered up.
  //
  // In a transform stream, the written data is placed in a buffer.  When
  // _read(n) is called, it transforms the queued up data, calling the
  // buffered _write cb's as it consumes chunks.  If consuming a single
  // written chunk would result in multiple output chunks, then the first
  // outputted bit calls the readcb, and subsequent chunks just go into
  // the read buffer, and will cause it to emit 'readable' if necessary.
  //
  // This way, back-pressure is actually determined by the reading side,
  // since _read has to be called to start processing a new chunk.  However,
  // a pathological inflate type of transform can cause excessive buffering
  // here.  For example, imagine a stream where every byte of input is
  // interpreted as an integer from 0-255, and then results in that many
  // bytes of output.  Writing the 4 bytes {ff,ff,ff,ff} would result in
  // 1kb of data being output.  In this case, you could write a very small
  // amount of input, and end up with a very large amount of output.  In
  // such a pathological inflating mechanism, there'd be no way to tell
  // the system to stop doing the transform.  A single 4MB write could
  // cause the system to run out of memory.
  //
  // However, even in such a pathological case, only a single written chunk
  // would be consumed, and then the rest would wait (un-transformed) until
  // the results of the previous transformed chunk were consumed.
  
  module.exports = Transform;
  
  var Duplex = require('./_stream_duplex');
  
  /*<replacement>*/
  var util = require('core-util-is');
  util.inherits = require('inherits');
  /*</replacement>*/
  
  util.inherits(Transform, Duplex);
  
  
  function TransformState(options, stream) {
    this.afterTransform = function(er, data) {
      return afterTransform(stream, er, data);
    };
  
    this.needTransform = false;
    this.transforming = false;
    this.writecb = null;
    this.writechunk = null;
  }
  
  function afterTransform(stream, er, data) {
    var ts = stream._transformState;
    ts.transforming = false;
  
    var cb = ts.writecb;
  
    if (!cb)
      return stream.emit('error', new Error('no writecb in Transform class'));
  
    ts.writechunk = null;
    ts.writecb = null;
  
    if (data !== null && data !== undefined)
      stream.push(data);
  
    if (cb)
      cb(er);
  
    var rs = stream._readableState;
    rs.reading = false;
    if (rs.needReadable || rs.length < rs.highWaterMark) {
      stream._read(rs.highWaterMark);
    }
  }
  
  
  function Transform(options) {
    if (!(this instanceof Transform))
      return new Transform(options);
  
    Duplex.call(this, options);
  
    var ts = this._transformState = new TransformState(options, this);
  
    // when the writable side finishes, then flush out anything remaining.
    var stream = this;
  
    // start out asking for a readable event once data is transformed.
    this._readableState.needReadable = true;
  
    // we have implemented the _read method, and done the other things
    // that Readable wants before the first _read call, so unset the
    // sync guard flag.
    this._readableState.sync = false;
  
    this.once('finish', function() {
      if ('function' === typeof this._flush)
        this._flush(function(er) {
          done(stream, er);
        });
      else
        done(stream);
    });
  }
  
  Transform.prototype.push = function(chunk, encoding) {
    this._transformState.needTransform = false;
    return Duplex.prototype.push.call(this, chunk, encoding);
  };
  
  // This is the part where you do stuff!
  // override this function in implementation classes.
  // 'chunk' is an input chunk.
  //
  // Call `push(newChunk)` to pass along transformed output
  // to the readable side.  You may call 'push' zero or more times.
  //
  // Call `cb(err)` when you are done with this chunk.  If you pass
  // an error, then that'll put the hurt on the whole operation.  If you
  // never call cb(), then you'll never get another chunk.
  Transform.prototype._transform = function(chunk, encoding, cb) {
    throw new Error('not implemented');
  };
  
  Transform.prototype._write = function(chunk, encoding, cb) {
    var ts = this._transformState;
    ts.writecb = cb;
    ts.writechunk = chunk;
    ts.writeencoding = encoding;
    if (!ts.transforming) {
      var rs = this._readableState;
      if (ts.needTransform ||
          rs.needReadable ||
          rs.length < rs.highWaterMark)
        this._read(rs.highWaterMark);
    }
  };
  
  // Doesn't matter what the args are here.
  // _transform does all the work.
  // That we got here means that the readable side wants more data.
  Transform.prototype._read = function(n) {
    var ts = this._transformState;
  
    if (ts.writechunk !== null && ts.writecb && !ts.transforming) {
      ts.transforming = true;
      this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform);
    } else {
      // mark that we need a transform, so that any data that comes in
      // will get processed, now that we've asked for it.
      ts.needTransform = true;
    }
  };
  
  
  function done(stream, er) {
    if (er)
      return stream.emit('error', er);
  
    // if there's nothing in the write buffer, then that means
    // that nothing more will ever be provided
    var ws = stream._writableState;
    var rs = stream._readableState;
    var ts = stream._transformState;
  
    if (ws.length)
      throw new Error('calling transform done when ws.length != 0');
  
    if (ts.transforming)
      throw new Error('calling transform done when still transforming');
  
    return stream.push(null);
  }
  
  },{"./_stream_duplex":60,"core-util-is":65,"inherits":52}],64:[function(require,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.
  
  // A bit simpler than readable streams.
  // Implement an async ._write(chunk, cb), and it'll handle all
  // the drain event emission and buffering.
  
  module.exports = Writable;
  
  /*<replacement>*/
  var Buffer = require('buffer').Buffer;
  /*</replacement>*/
  
  Writable.WritableState = WritableState;
  
  
  /*<replacement>*/
  var util = require('core-util-is');
  util.inherits = require('inherits');
  /*</replacement>*/
  
  var Stream = require('stream');
  
  util.inherits(Writable, Stream);
  
  function WriteReq(chunk, encoding, cb) {
    this.chunk = chunk;
    this.encoding = encoding;
    this.callback = cb;
  }
  
  function WritableState(options, stream) {
    options = options || {};
  
    // the point at which write() starts returning false
    // Note: 0 is a valid value, means that we always return false if
    // the entire buffer is not flushed immediately on write()
    var hwm = options.highWaterMark;
    this.highWaterMark = (hwm || hwm === 0) ? hwm : 16 * 1024;
  
    // object stream flag to indicate whether or not this stream
    // contains buffers or objects.
    this.objectMode = !!options.objectMode;
  
    // cast to ints.
    this.highWaterMark = ~~this.highWaterMark;
  
    this.needDrain = false;
    // at the start of calling end()
    this.ending = false;
    // when end() has been called, and returned
    this.ended = false;
    // when 'finish' is emitted
    this.finished = false;
  
    // should we decode strings into buffers before passing to _write?
    // this is here so that some node-core streams can optimize string
    // handling at a lower level.
    var noDecode = options.decodeStrings === false;
    this.decodeStrings = !noDecode;
  
    // Crypto is kind of old and crusty.  Historically, its default string
    // encoding is 'binary' so we have to make this configurable.
    // Everything else in the universe uses 'utf8', though.
    this.defaultEncoding = options.defaultEncoding || 'utf8';
  
    // not an actual buffer we keep track of, but a measurement
    // of how much we're waiting to get pushed to some underlying
    // socket or file.
    this.length = 0;
  
    // a flag to see when we're in the middle of a write.
    this.writing = false;
  
    // a flag to be able to tell if the onwrite cb is called immediately,
    // or on a later tick.  We set this to true at first, becuase any
    // actions that shouldn't happen until "later" should generally also
    // not happen before the first write call.
    this.sync = true;
  
    // a flag to know if we're processing previously buffered items, which
    // may call the _write() callback in the same tick, so that we don't
    // end up in an overlapped onwrite situation.
    this.bufferProcessing = false;
  
    // the callback that's passed to _write(chunk,cb)
    this.onwrite = function(er) {
      onwrite(stream, er);
    };
  
    // the callback that the user supplies to write(chunk,encoding,cb)
    this.writecb = null;
  
    // the amount that is being written when _write is called.
    this.writelen = 0;
  
    this.buffer = [];
  
    // True if the error was already emitted and should not be thrown again
    this.errorEmitted = false;
  }
  
  function Writable(options) {
    var Duplex = require('./_stream_duplex');
  
    // Writable ctor is applied to Duplexes, though they're not
    // instanceof Writable, they're instanceof Readable.
    if (!(this instanceof Writable) && !(this instanceof Duplex))
      return new Writable(options);
  
    this._writableState = new WritableState(options, this);
  
    // legacy.
    this.writable = true;
  
    Stream.call(this);
  }
  
  // Otherwise people can pipe Writable streams, which is just wrong.
  Writable.prototype.pipe = function() {
    this.emit('error', new Error('Cannot pipe. Not readable.'));
  };
  
  
  function writeAfterEnd(stream, state, cb) {
    var er = new Error('write after end');
    // TODO: defer error events consistently everywhere, not just the cb
    stream.emit('error', er);
    process.nextTick(function() {
      cb(er);
    });
  }
  
  // If we get something that is not a buffer, string, null, or undefined,
  // and we're not in objectMode, then that's an error.
  // Otherwise stream chunks are all considered to be of length=1, and the
  // watermarks determine how many objects to keep in the buffer, rather than
  // how many bytes or characters.
  function validChunk(stream, state, chunk, cb) {
    var valid = true;
    if (!Buffer.isBuffer(chunk) &&
        'string' !== typeof chunk &&
        chunk !== null &&
        chunk !== undefined &&
        !state.objectMode) {
      var er = new TypeError('Invalid non-string/buffer chunk');
      stream.emit('error', er);
      process.nextTick(function() {
        cb(er);
      });
      valid = false;
    }
    return valid;
  }
  
  Writable.prototype.write = function(chunk, encoding, cb) {
    var state = this._writableState;
    var ret = false;
  
    if (typeof encoding === 'function') {
      cb = encoding;
      encoding = null;
    }
  
    if (Buffer.isBuffer(chunk))
      encoding = 'buffer';
    else if (!encoding)
      encoding = state.defaultEncoding;
  
    if (typeof cb !== 'function')
      cb = function() {};
  
    if (state.ended)
      writeAfterEnd(this, state, cb);
    else if (validChunk(this, state, chunk, cb))
      ret = writeOrBuffer(this, state, chunk, encoding, cb);
  
    return ret;
  };
  
  function decodeChunk(state, chunk, encoding) {
    if (!state.objectMode &&
        state.decodeStrings !== false &&
        typeof chunk === 'string') {
      chunk = new Buffer(chunk, encoding);
    }
    return chunk;
  }
  
  // if we're already writing something, then just put this
  // in the queue, and wait our turn.  Otherwise, call _write
  // If we return false, then we need a drain event, so set that flag.
  function writeOrBuffer(stream, state, chunk, encoding, cb) {
    chunk = decodeChunk(state, chunk, encoding);
    if (Buffer.isBuffer(chunk))
      encoding = 'buffer';
    var len = state.objectMode ? 1 : chunk.length;
  
    state.length += len;
  
    var ret = state.length < state.highWaterMark;
    // we must ensure that previous needDrain will not be reset to false.
    if (!ret)
      state.needDrain = true;
  
    if (state.writing)
      state.buffer.push(new WriteReq(chunk, encoding, cb));
    else
      doWrite(stream, state, len, chunk, encoding, cb);
  
    return ret;
  }
  
  function doWrite(stream, state, len, chunk, encoding, cb) {
    state.writelen = len;
    state.writecb = cb;
    state.writing = true;
    state.sync = true;
    stream._write(chunk, encoding, state.onwrite);
    state.sync = false;
  }
  
  function onwriteError(stream, state, sync, er, cb) {
    if (sync)
      process.nextTick(function() {
        cb(er);
      });
    else
      cb(er);
  
    stream._writableState.errorEmitted = true;
    stream.emit('error', er);
  }
  
  function onwriteStateUpdate(state) {
    state.writing = false;
    state.writecb = null;
    state.length -= state.writelen;
    state.writelen = 0;
  }
  
  function onwrite(stream, er) {
    var state = stream._writableState;
    var sync = state.sync;
    var cb = state.writecb;
  
    onwriteStateUpdate(state);
  
    if (er)
      onwriteError(stream, state, sync, er, cb);
    else {
      // Check if we're actually ready to finish, but don't emit yet
      var finished = needFinish(stream, state);
  
      if (!finished && !state.bufferProcessing && state.buffer.length)
        clearBuffer(stream, state);
  
      if (sync) {
        process.nextTick(function() {
          afterWrite(stream, state, finished, cb);
        });
      } else {
        afterWrite(stream, state, finished, cb);
      }
    }
  }
  
  function afterWrite(stream, state, finished, cb) {
    if (!finished)
      onwriteDrain(stream, state);
    cb();
    if (finished)
      finishMaybe(stream, state);
  }
  
  // Must force callback to be called on nextTick, so that we don't
  // emit 'drain' before the write() consumer gets the 'false' return
  // value, and has a chance to attach a 'drain' listener.
  function onwriteDrain(stream, state) {
    if (state.length === 0 && state.needDrain) {
      state.needDrain = false;
      stream.emit('drain');
    }
  }
  
  
  // if there's something in the buffer waiting, then process it
  function clearBuffer(stream, state) {
    state.bufferProcessing = true;
  
    for (var c = 0; c < state.buffer.length; c++) {
      var entry = state.buffer[c];
      var chunk = entry.chunk;
      var encoding = entry.encoding;
      var cb = entry.callback;
      var len = state.objectMode ? 1 : chunk.length;
  
      doWrite(stream, state, len, chunk, encoding, cb);
  
      // if we didn't call the onwrite immediately, then
      // it means that we need to wait until it does.
      // also, that means that the chunk and cb are currently
      // being processed, so move the buffer counter past them.
      if (state.writing) {
        c++;
        break;
      }
    }
  
    state.bufferProcessing = false;
    if (c < state.buffer.length)
      state.buffer = state.buffer.slice(c);
    else
      state.buffer.length = 0;
  }
  
  Writable.prototype._write = function(chunk, encoding, cb) {
    cb(new Error('not implemented'));
  };
  
  Writable.prototype.end = function(chunk, encoding, cb) {
    var state = this._writableState;
  
    if (typeof chunk === 'function') {
      cb = chunk;
      chunk = null;
      encoding = null;
    } else if (typeof encoding === 'function') {
      cb = encoding;
      encoding = null;
    }
  
    if (typeof chunk !== 'undefined' && chunk !== null)
      this.write(chunk, encoding);
  
    // ignore unnecessary end() calls.
    if (!state.ending && !state.finished)
      endWritable(this, state, cb);
  };
  
  
  function needFinish(stream, state) {
    return (state.ending &&
            state.length === 0 &&
            !state.finished &&
            !state.writing);
  }
  
  function finishMaybe(stream, state) {
    var need = needFinish(stream, state);
    if (need) {
      state.finished = true;
      stream.emit('finish');
    }
    return need;
  }
  
  function endWritable(stream, state, cb) {
    state.ending = true;
    finishMaybe(stream, state);
    if (cb) {
      if (state.finished)
        process.nextTick(cb);
      else
        stream.once('finish', cb);
    }
    state.ended = true;
  }
  
  }).call(this,require('_process'))
  },{"./_stream_duplex":60,"_process":54,"buffer":42,"core-util-is":65,"inherits":52,"stream":70}],65:[function(require,module,exports){
  (function (Buffer){
  // 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.
  
  // 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;
  
  function isBuffer(arg) {
    return Buffer.isBuffer(arg);
  }
  exports.isBuffer = isBuffer;
  
  function objectToString(o) {
    return Object.prototype.toString.call(o);
  }
  }).call(this,require("buffer").Buffer)
  },{"buffer":42}],66:[function(require,module,exports){
  module.exports = require("./lib/_stream_passthrough.js")
  
  },{"./lib/_stream_passthrough.js":61}],67:[function(require,module,exports){
  var Stream = require('stream'); // hack to fix a circular dependency issue when used with browserify
  exports = module.exports = require('./lib/_stream_readable.js');
  exports.Stream = Stream;
  exports.Readable = exports;
  exports.Writable = require('./lib/_stream_writable.js');
  exports.Duplex = require('./lib/_stream_duplex.js');
  exports.Transform = require('./lib/_stream_transform.js');
  exports.PassThrough = require('./lib/_stream_passthrough.js');
  
  },{"./lib/_stream_duplex.js":60,"./lib/_stream_passthrough.js":61,"./lib/_stream_readable.js":62,"./lib/_stream_transform.js":63,"./lib/_stream_writable.js":64,"stream":70}],68:[function(require,module,exports){
  module.exports = require("./lib/_stream_transform.js")
  
  },{"./lib/_stream_transform.js":63}],69:[function(require,module,exports){
  module.exports = require("./lib/_stream_writable.js")
  
  },{"./lib/_stream_writable.js":64}],70:[function(require,module,exports){
  // 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.
  
  module.exports = Stream;
  
  var EE = require('events').EventEmitter;
  var inherits = require('inherits');
  
  inherits(Stream, EE);
  Stream.Readable = require('readable-stream/readable.js');
  Stream.Writable = require('readable-stream/writable.js');
  Stream.Duplex = require('readable-stream/duplex.js');
  Stream.Transform = require('readable-stream/transform.js');
  Stream.PassThrough = require('readable-stream/passthrough.js');
  
  // Backwards-compat with node 0.4.x
  Stream.Stream = Stream;
  
  
  
  // old-style streams.  Note that the pipe method (the only relevant
  // part of this class) is overridden in the Readable class.
  
  function Stream() {
    EE.call(this);
  }
  
  Stream.prototype.pipe = function(dest, options) {
    var source = this;
  
    function ondata(chunk) {
      if (dest.writable) {
        if (false === dest.write(chunk) && source.pause) {
          source.pause();
        }
      }
    }
  
    source.on('data', ondata);
  
    function ondrain() {
      if (source.readable && source.resume) {
        source.resume();
      }
    }
  
    dest.on('drain', ondrain);
  
    // If the 'end' option is not supplied, dest.end() will be called when
    // source gets the 'end' or 'close' events.  Only dest.end() once.
    if (!dest._isStdio && (!options || options.end !== false)) {
      source.on('end', onend);
      source.on('close', onclose);
    }
  
    var didOnEnd = false;
    function onend() {
      if (didOnEnd) return;
      didOnEnd = true;
  
      dest.end();
    }
  
  
    function onclose() {
      if (didOnEnd) return;
      didOnEnd = true;
  
      if (typeof dest.destroy === 'function') dest.destroy();
    }
  
    // don't leave dangling pipes when there are errors.
    function onerror(er) {
      cleanup();
      if (EE.listenerCount(this, 'error') === 0) {
        throw er; // Unhandled stream error in pipe.
      }
    }
  
    source.on('error', onerror);
    dest.on('error', onerror);
  
    // remove all the event listeners that were added.
    function cleanup() {
      source.removeListener('data', ondata);
      dest.removeListener('drain', ondrain);
  
      source.removeListener('end', onend);
      source.removeListener('close', onclose);
  
      source.removeListener('error', onerror);
      dest.removeListener('error', onerror);
  
      source.removeListener('end', cleanup);
      source.removeListener('close', cleanup);
  
      dest.removeListener('close', cleanup);
    }
  
    source.on('end', cleanup);
    source.on('close', cleanup);
  
    dest.on('close', cleanup);
  
    dest.emit('pipe', source);
  
    // Allow for unix-like usage: A.pipe(B).pipe(C)
    return dest;
  };
  
  },{"events":46,"inherits":52,"readable-stream/duplex.js":59,"readable-stream/passthrough.js":66,"readable-stream/readable.js":67,"readable-stream/transform.js":68,"readable-stream/writable.js":69}],71:[function(require,module,exports){
  // 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 Buffer = require('buffer').Buffer;
  
  var isBufferEncoding = Buffer.isEncoding
    || function(encoding) {
         switch (encoding && encoding.toLowerCase()) {
           case 'hex': case 'utf8': case 'utf-8': case 'ascii': case 'binary': case 'base64': case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': case 'raw': return true;
           default: return false;
         }
       }
  
  
  function assertEncoding(encoding) {
    if (encoding && !isBufferEncoding(encoding)) {
      throw new Error('Unknown encoding: ' + encoding);
    }
  }
  
  // StringDecoder provides an interface for efficiently splitting a series of
  // buffers into a series of JS strings without breaking apart multi-byte
  // characters. CESU-8 is handled as part of the UTF-8 encoding.
  //
  // @TODO Handling all encodings inside a single object makes it very difficult
  // to reason about this code, so it should be split up in the future.
  // @TODO There should be a utf8-strict encoding that rejects invalid UTF-8 code
  // points as used by CESU-8.
  var StringDecoder = exports.StringDecoder = function(encoding) {
    this.encoding = (encoding || 'utf8').toLowerCase().replace(/[-_]/, '');
    assertEncoding(encoding);
    switch (this.encoding) {
      case 'utf8':
        // CESU-8 represents each of Surrogate Pair by 3-bytes
        this.surrogateSize = 3;
        break;
      case 'ucs2':
      case 'utf16le':
        // UTF-16 represents each of Surrogate Pair by 2-bytes
        this.surrogateSize = 2;
        this.detectIncompleteChar = utf16DetectIncompleteChar;
        break;
      case 'base64':
        // Base-64 stores 3 bytes in 4 chars, and pads the remainder.
        this.surrogateSize = 3;
        this.detectIncompleteChar = base64DetectIncompleteChar;
        break;
      default:
        this.write = passThroughWrite;
        return;
    }
  
    // Enough space to store all bytes of a single character. UTF-8 needs 4
    // bytes, but CESU-8 may require up to 6 (3 bytes per surrogate).
    this.charBuffer = new Buffer(6);
    // Number of bytes received for the current incomplete multi-byte character.
    this.charReceived = 0;
    // Number of bytes expected for the current incomplete multi-byte character.
    this.charLength = 0;
  };
  
  
  // write decodes the given buffer and returns it as JS string that is
  // guaranteed to not contain any partial multi-byte characters. Any partial
  // character found at the end of the buffer is buffered up, and will be
  // returned when calling write again with the remaining bytes.
  //
  // Note: Converting a Buffer containing an orphan surrogate to a String
  // currently works, but converting a String to a Buffer (via `new Buffer`, or
  // Buffer#write) will replace incomplete surrogates with the unicode
  // replacement character. See https://codereview.chromium.org/121173009/ .
  StringDecoder.prototype.write = function(buffer) {
    var charStr = '';
    // if our last write ended with an incomplete multibyte character
    while (this.charLength) {
      // determine how many remaining bytes this buffer has to offer for this char
      var available = (buffer.length >= this.charLength - this.charReceived) ?
          this.charLength - this.charReceived :
          buffer.length;
  
      // add the new bytes to the char buffer
      buffer.copy(this.charBuffer, this.charReceived, 0, available);
      this.charReceived += available;
  
      if (this.charReceived < this.charLength) {
        // still not enough chars in this buffer? wait for more ...
        return '';
      }
  
      // remove bytes belonging to the current character from the buffer
      buffer = buffer.slice(available, buffer.length);
  
      // get the character that was split
      charStr = this.charBuffer.slice(0, this.charLength).toString(this.encoding);
  
      // CESU-8: lead surrogate (D800-DBFF) is also the incomplete character
      var charCode = charStr.charCodeAt(charStr.length - 1);
      if (charCode >= 0xD800 && charCode <= 0xDBFF) {
        this.charLength += this.surrogateSize;
        charStr = '';
        continue;
      }
      this.charReceived = this.charLength = 0;
  
      // if there are no more bytes in this buffer, just emit our char
      if (buffer.length === 0) {
        return charStr;
      }
      break;
    }
  
    // determine and set charLength / charReceived
    this.detectIncompleteChar(buffer);
  
    var end = buffer.length;
    if (this.charLength) {
      // buffer the incomplete character bytes we got
      buffer.copy(this.charBuffer, 0, buffer.length - this.charReceived, end);
      end -= this.charReceived;
    }
  
    charStr += buffer.toString(this.encoding, 0, end);
  
    var end = charStr.length - 1;
    var charCode = charStr.charCodeAt(end);
    // CESU-8: lead surrogate (D800-DBFF) is also the incomplete character
    if (charCode >= 0xD800 && charCode <= 0xDBFF) {
      var size = this.surrogateSize;
      this.charLength += size;
      this.charReceived += size;
      this.charBuffer.copy(this.charBuffer, size, 0, size);
      buffer.copy(this.charBuffer, 0, 0, size);
      return charStr.substring(0, end);
    }
  
    // or just emit the charStr
    return charStr;
  };
  
  // detectIncompleteChar determines if there is an incomplete UTF-8 character at
  // the end of the given buffer. If so, it sets this.charLength to the byte
  // length that character, and sets this.charReceived to the number of bytes
  // that are available for this character.
  StringDecoder.prototype.detectIncompleteChar = function(buffer) {
    // determine how many bytes we have to check at the end of this buffer
    var i = (buffer.length >= 3) ? 3 : buffer.length;
  
    // Figure out if one of the last i bytes of our buffer announces an
    // incomplete char.
    for (; i > 0; i--) {
      var c = buffer[buffer.length - i];
  
      // See http://en.wikipedia.org/wiki/UTF-8#Description
  
      // 110XXXXX
      if (i == 1 && c >> 5 == 0x06) {
        this.charLength = 2;
        break;
      }
  
      // 1110XXXX
      if (i <= 2 && c >> 4 == 0x0E) {
        this.charLength = 3;
        break;
      }
  
      // 11110XXX
      if (i <= 3 && c >> 3 == 0x1E) {
        this.charLength = 4;
        break;
      }
    }
    this.charReceived = i;
  };
  
  StringDecoder.prototype.end = function(buffer) {
    var res = '';
    if (buffer && buffer.length)
      res = this.write(buffer);
  
    if (this.charReceived) {
      var cr = this.charReceived;
      var buf = this.charBuffer;
      var enc = this.encoding;
      res += buf.slice(0, cr).toString(enc);
    }
  
    return res;
  };
  
  function passThroughWrite(buffer) {
    return buffer.toString(this.encoding);
  }
  
  function utf16DetectIncompleteChar(buffer) {
    this.charReceived = buffer.length % 2;
    this.charLength = this.charReceived ? 2 : 0;
  }
  
  function base64DetectIncompleteChar(buffer) {
    this.charReceived = buffer.length % 3;
    this.charLength = this.charReceived ? 3 : 0;
  }
  
  },{"buffer":42}],72:[function(require,module,exports){
  // 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 punycode = require('punycode');
  
  exports.parse = urlParse;
  exports.resolve = urlResolve;
  exports.resolveObject = urlResolveObject;
  exports.format = urlFormat;
  
  exports.Url = Url;
  
  function Url() {
    this.protocol = null;
    this.slashes = null;
    this.auth = null;
    this.host = null;
    this.port = null;
    this.hostname = null;
    this.hash = null;
    this.search = null;
    this.query = null;
    this.pathname = null;
    this.path = null;
    this.href = null;
  }
  
  // Reference: RFC 3986, RFC 1808, RFC 2396
  
  // define these here so at least they only have to be
  // compiled once on the first module load.
  var protocolPattern = /^([a-z0-9.+-]+:)/i,
      portPattern = /:[0-9]*$/,
  
      // RFC 2396: characters reserved for delimiting URLs.
      // We actually just auto-escape these.
      delims = ['<', '>', '"', '`', ' ', '\r', '\n', '\t'],
  
      // RFC 2396: characters not allowed for various reasons.
      unwise = ['{', '}', '|', '\\', '^', '`'].concat(delims),
  
      // Allowed by RFCs, but cause of XSS attacks.  Always escape these.
      autoEscape = ['\''].concat(unwise),
      // Characters that are never ever allowed in a hostname.
      // Note that any invalid chars are also handled, but these
      // are the ones that are *expected* to be seen, so we fast-path
      // them.
      nonHostChars = ['%', '/', '?', ';', '#'].concat(autoEscape),
      hostEndingChars = ['/', '?', '#'],
      hostnameMaxLen = 255,
      hostnamePartPattern = /^[a-z0-9A-Z_-]{0,63}$/,
      hostnamePartStart = /^([a-z0-9A-Z_-]{0,63})(.*)$/,
      // protocols that can allow "unsafe" and "unwise" chars.
      unsafeProtocol = {
        'javascript': true,
        'javascript:': true
      },
      // protocols that never have a hostname.
      hostlessProtocol = {
        'javascript': true,
        'javascript:': true
      },
      // protocols that always contain a // bit.
      slashedProtocol = {
        'http': true,
        'https': true,
        'ftp': true,
        'gopher': true,
        'file': true,
        'http:': true,
        'https:': true,
        'ftp:': true,
        'gopher:': true,
        'file:': true
      },
      querystring = require('querystring');
  
  function urlParse(url, parseQueryString, slashesDenoteHost) {
    if (url && isObject(url) && url instanceof Url) return url;
  
    var u = new Url;
    u.parse(url, parseQueryString, slashesDenoteHost);
    return u;
  }
  
  Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) {
    if (!isString(url)) {
      throw new TypeError("Parameter 'url' must be a string, not " + typeof url);
    }
  
    var rest = url;
  
    // trim before proceeding.
    // This is to support parse stuff like "  http://foo.com  \n"
    rest = rest.trim();
  
    var proto = protocolPattern.exec(rest);
    if (proto) {
      proto = proto[0];
      var lowerProto = proto.toLowerCase();
      this.protocol = lowerProto;
      rest = rest.substr(proto.length);
    }
  
    // figure out if it's got a host
    // user@server is *always* interpreted as a hostname, and url
    // resolution will treat //foo/bar as host=foo,path=bar because that's
    // how the browser resolves relative URLs.
    if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) {
      var slashes = rest.substr(0, 2) === '//';
      if (slashes && !(proto && hostlessProtocol[proto])) {
        rest = rest.substr(2);
        this.slashes = true;
      }
    }
  
    if (!hostlessProtocol[proto] &&
        (slashes || (proto && !slashedProtocol[proto]))) {
  
      // there's a hostname.
      // the first instance of /, ?, ;, or # ends the host.
      //
      // If there is an @ in the hostname, then non-host chars *are* allowed
      // to the left of the last @ sign, unless some host-ending character
      // comes *before* the @-sign.
      // URLs are obnoxious.
      //
      // ex:
      // http://a@b@c/ => user:a@b host:c
      // http://a@b?@c => user:a host:c path:/?@c
  
      // v0.12 TODO(isaacs): This is not quite how Chrome does things.
      // Review our test case against browsers more comprehensively.
  
      // find the first instance of any hostEndingChars
      var hostEnd = -1;
      for (var i = 0; i < hostEndingChars.length; i++) {
        var hec = rest.indexOf(hostEndingChars[i]);
        if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))
          hostEnd = hec;
      }
  
      // at this point, either we have an explicit point where the
      // auth portion cannot go past, or the last @ char is the decider.
      var auth, atSign;
      if (hostEnd === -1) {
        // atSign can be anywhere.
        atSign = rest.lastIndexOf('@');
      } else {
        // atSign must be in auth portion.
        // http://a@b/c@d => host:b auth:a path:/c@d
        atSign = rest.lastIndexOf('@', hostEnd);
      }
  
      // Now we have a portion which is definitely the auth.
      // Pull that off.
      if (atSign !== -1) {
        auth = rest.slice(0, atSign);
        rest = rest.slice(atSign + 1);
        this.auth = decodeURIComponent(auth);
      }
  
      // the host is the remaining to the left of the first non-host char
      hostEnd = -1;
      for (var i = 0; i < nonHostChars.length; i++) {
        var hec = rest.indexOf(nonHostChars[i]);
        if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))
          hostEnd = hec;
      }
      // if we still have not hit it, then the entire thing is a host.
      if (hostEnd === -1)
        hostEnd = rest.length;
  
      this.host = rest.slice(0, hostEnd);
      rest = rest.slice(hostEnd);
  
      // pull out port.
      this.parseHost();
  
      // we've indicated that there is a hostname,
      // so even if it's empty, it has to be present.
      this.hostname = this.hostname || '';
  
      // if hostname begins with [ and ends with ]
      // assume that it's an IPv6 address.
      var ipv6Hostname = this.hostname[0] === '[' &&
          this.hostname[this.hostname.length - 1] === ']';
  
      // validate a little.
      if (!ipv6Hostname) {
        var hostparts = this.hostname.split(/\./);
        for (var i = 0, l = hostparts.length; i < l; i++) {
          var part = hostparts[i];
          if (!part) continue;
          if (!part.match(hostnamePartPattern)) {
            var newpart = '';
            for (var j = 0, k = part.length; j < k; j++) {
              if (part.charCodeAt(j) > 127) {
                // we replace non-ASCII char with a temporary placeholder
                // we need this to make sure size of hostname is not
                // broken by replacing non-ASCII by nothing
                newpart += 'x';
              } else {
                newpart += part[j];
              }
            }
            // we test again with ASCII char only
            if (!newpart.match(hostnamePartPattern)) {
              var validParts = hostparts.slice(0, i);
              var notHost = hostparts.slice(i + 1);
              var bit = part.match(hostnamePartStart);
              if (bit) {
                validParts.push(bit[1]);
                notHost.unshift(bit[2]);
              }
              if (notHost.length) {
                rest = '/' + notHost.join('.') + rest;
              }
              this.hostname = validParts.join('.');
              break;
            }
          }
        }
      }
  
      if (this.hostname.length > hostnameMaxLen) {
        this.hostname = '';
      } else {
        // hostnames are always lower case.
        this.hostname = this.hostname.toLowerCase();
      }
  
      if (!ipv6Hostname) {
        // IDNA Support: Returns a puny coded representation of "domain".
        // It only converts the part of the domain name that
        // has non ASCII characters. I.e. it dosent matter if
        // you call it with a domain that already is in ASCII.
        var domainArray = this.hostname.split('.');
        var newOut = [];
        for (var i = 0; i < domainArray.length; ++i) {
          var s = domainArray[i];
          newOut.push(s.match(/[^A-Za-z0-9_-]/) ?
              'xn--' + punycode.encode(s) : s);
        }
        this.hostname = newOut.join('.');
      }
  
      var p = this.port ? ':' + this.port : '';
      var h = this.hostname || '';
      this.host = h + p;
      this.href += this.host;
  
      // strip [ and ] from the hostname
      // the host field still retains them, though
      if (ipv6Hostname) {
        this.hostname = this.hostname.substr(1, this.hostname.length - 2);
        if (rest[0] !== '/') {
          rest = '/' + rest;
        }
      }
    }
  
    // now rest is set to the post-host stuff.
    // chop off any delim chars.
    if (!unsafeProtocol[lowerProto]) {
  
      // First, make 100% sure that any "autoEscape" chars get
      // escaped, even if encodeURIComponent doesn't think they
      // need to be.
      for (var i = 0, l = autoEscape.length; i < l; i++) {
        var ae = autoEscape[i];
        var esc = encodeURIComponent(ae);
        if (esc === ae) {
          esc = escape(ae);
        }
        rest = rest.split(ae).join(esc);
      }
    }
  
  
    // chop off from the tail first.
    var hash = rest.indexOf('#');
    if (hash !== -1) {
      // got a fragment string.
      this.hash = rest.substr(hash);
      rest = rest.slice(0, hash);
    }
    var qm = rest.indexOf('?');
    if (qm !== -1) {
      this.search = rest.substr(qm);
      this.query = rest.substr(qm + 1);
      if (parseQueryString) {
        this.query = querystring.parse(this.query);
      }
      rest = rest.slice(0, qm);
    } else if (parseQueryString) {
      // no query string, but parseQueryString still requested
      this.search = '';
      this.query = {};
    }
    if (rest) this.pathname = rest;
    if (slashedProtocol[lowerProto] &&
        this.hostname && !this.pathname) {
      this.pathname = '/';
    }
  
    //to support http.request
    if (this.pathname || this.search) {
      var p = this.pathname || '';
      var s = this.search || '';
      this.path = p + s;
    }
  
    // finally, reconstruct the href based on what has been validated.
    this.href = this.format();
    return this;
  };
  
  // format a parsed object into a url string
  function urlFormat(obj) {
    // ensure it's an object, and not a string url.
    // If it's an obj, this is a no-op.
    // this way, you can call url_format() on strings
    // to clean up potentially wonky urls.
    if (isString(obj)) obj = urlParse(obj);
    if (!(obj instanceof Url)) return Url.prototype.format.call(obj);
    return obj.format();
  }
  
  Url.prototype.format = function() {
    var auth = this.auth || '';
    if (auth) {
      auth = encodeURIComponent(auth);
      auth = auth.replace(/%3A/i, ':');
      auth += '@';
    }
  
    var protocol = this.protocol || '',
        pathname = this.pathname || '',
        hash = this.hash || '',
        host = false,
        query = '';
  
    if (this.host) {
      host = auth + this.host;
    } else if (this.hostname) {
      host = auth + (this.hostname.indexOf(':') === -1 ?
          this.hostname :
          '[' + this.hostname + ']');
      if (this.port) {
        host += ':' + this.port;
      }
    }
  
    if (this.query &&
        isObject(this.query) &&
        Object.keys(this.query).length) {
      query = querystring.stringify(this.query);
    }
  
    var search = this.search || (query && ('?' + query)) || '';
  
    if (protocol && protocol.substr(-1) !== ':') protocol += ':';
  
    // only the slashedProtocols get the //.  Not mailto:, xmpp:, etc.
    // unless they had them to begin with.
    if (this.slashes ||
        (!protocol || slashedProtocol[protocol]) && host !== false) {
      host = '//' + (host || '');
      if (pathname && pathname.charAt(0) !== '/') pathname = '/' + pathname;
    } else if (!host) {
      host = '';
    }
  
    if (hash && hash.charAt(0) !== '#') hash = '#' + hash;
    if (search && search.charAt(0) !== '?') search = '?' + search;
  
    pathname = pathname.replace(/[?#]/g, function(match) {
      return encodeURIComponent(match);
    });
    search = search.replace('#', '%23');
  
    return protocol + host + pathname + search + hash;
  };
  
  function urlResolve(source, relative) {
    return urlParse(source, false, true).resolve(relative);
  }
  
  Url.prototype.resolve = function(relative) {
    return this.resolveObject(urlParse(relative, false, true)).format();
  };
  
  function urlResolveObject(source, relative) {
    if (!source) return relative;
    return urlParse(source, false, true).resolveObject(relative);
  }
  
  Url.prototype.resolveObject = function(relative) {
    if (isString(relative)) {
      var rel = new Url();
      rel.parse(relative, false, true);
      relative = rel;
    }
  
    var result = new Url();
    Object.keys(this).forEach(function(k) {
      result[k] = this[k];
    }, this);
  
    // hash is always overridden, no matter what.
    // even href="" will remove it.
    result.hash = relative.hash;
  
    // if the relative url is empty, then there's nothing left to do here.
    if (relative.href === '') {
      result.href = result.format();
      return result;
    }
  
    // hrefs like //foo/bar always cut to the protocol.
    if (relative.slashes && !relative.protocol) {
      // take everything except the protocol from relative
      Object.keys(relative).forEach(function(k) {
        if (k !== 'protocol')
          result[k] = relative[k];
      });
  
      //urlParse appends trailing / to urls like http://www.example.com
      if (slashedProtocol[result.protocol] &&
          result.hostname && !result.pathname) {
        result.path = result.pathname = '/';
      }
  
      result.href = result.format();
      return result;
    }
  
    if (relative.protocol && relative.protocol !== result.protocol) {
      // if it's a known url protocol, then changing
      // the protocol does weird things
      // first, if it's not file:, then we MUST have a host,
      // and if there was a path
      // to begin with, then we MUST have a path.
      // if it is file:, then the host is dropped,
      // because that's known to be hostless.
      // anything else is assumed to be absolute.
      if (!slashedProtocol[relative.protocol]) {
        Object.keys(relative).forEach(function(k) {
          result[k] = relative[k];
        });
        result.href = result.format();
        return result;
      }
  
      result.protocol = relative.protocol;
      if (!relative.host && !hostlessProtocol[relative.protocol]) {
        var relPath = (relative.pathname || '').split('/');
        while (relPath.length && !(relative.host = relPath.shift()));
        if (!relative.host) relative.host = '';
        if (!relative.hostname) relative.hostname = '';
        if (relPath[0] !== '') relPath.unshift('');
        if (relPath.length < 2) relPath.unshift('');
        result.pathname = relPath.join('/');
      } else {
        result.pathname = relative.pathname;
      }
      result.search = relative.search;
      result.query = relative.query;
      result.host = relative.host || '';
      result.auth = relative.auth;
      result.hostname = relative.hostname || relative.host;
      result.port = relative.port;
      // to support http.request
      if (result.pathname || result.search) {
        var p = result.pathname || '';
        var s = result.search || '';
        result.path = p + s;
      }
      result.slashes = result.slashes || relative.slashes;
      result.href = result.format();
      return result;
    }
  
    var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'),
        isRelAbs = (
            relative.host ||
            relative.pathname && relative.pathname.charAt(0) === '/'
        ),
        mustEndAbs = (isRelAbs || isSourceAbs ||
                      (result.host && relative.pathname)),
        removeAllDots = mustEndAbs,
        srcPath = result.pathname && result.pathname.split('/') || [],
        relPath = relative.pathname && relative.pathname.split('/') || [],
        psychotic = result.protocol && !slashedProtocol[result.protocol];
  
    // if the url is a non-slashed url, then relative
    // links like ../.. should be able
    // to crawl up to the hostname, as well.  This is strange.
    // result.protocol has already been set by now.
    // Later on, put the first path part into the host field.
    if (psychotic) {
      result.hostname = '';
      result.port = null;
      if (result.host) {
        if (srcPath[0] === '') srcPath[0] = result.host;
        else srcPath.unshift(result.host);
      }
      result.host = '';
      if (relative.protocol) {
        relative.hostname = null;
        relative.port = null;
        if (relative.host) {
          if (relPath[0] === '') relPath[0] = relative.host;
          else relPath.unshift(relative.host);
        }
        relative.host = null;
      }
      mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === '');
    }
  
    if (isRelAbs) {
      // it's absolute.
      result.host = (relative.host || relative.host === '') ?
                    relative.host : result.host;
      result.hostname = (relative.hostname || relative.hostname === '') ?
                        relative.hostname : result.hostname;
      result.search = relative.search;
      result.query = relative.query;
      srcPath = relPath;
      // fall through to the dot-handling below.
    } else if (relPath.length) {
      // it's relative
      // throw away the existing file, and take the new path instead.
      if (!srcPath) srcPath = [];
      srcPath.pop();
      srcPath = srcPath.concat(relPath);
      result.search = relative.search;
      result.query = relative.query;
    } else if (!isNullOrUndefined(relative.search)) {
      // just pull out the search.
      // like href='?foo'.
      // Put this after the other two cases because it simplifies the booleans
      if (psychotic) {
        result.hostname = result.host = srcPath.shift();
        //occationaly the auth can get stuck only in host
        //this especialy happens in cases like
        //url.resolveObject('mailto:local1@domain1', 'local2@domain2')
        var authInHost = result.host && result.host.indexOf('@') > 0 ?
                         result.host.split('@') : false;
        if (authInHost) {
          result.auth = authInHost.shift();
          result.host = result.hostname = authInHost.shift();
        }
      }
      result.search = relative.search;
      result.query = relative.query;
      //to support http.request
      if (!isNull(result.pathname) || !isNull(result.search)) {
        result.path = (result.pathname ? result.pathname : '') +
                      (result.search ? result.search : '');
      }
      result.href = result.format();
      return result;
    }
  
    if (!srcPath.length) {
      // no path at all.  easy.
      // we've already handled the other stuff above.
      result.pathname = null;
      //to support http.request
      if (result.search) {
        result.path = '/' + result.search;
      } else {
        result.path = null;
      }
      result.href = result.format();
      return result;
    }
  
    // if a url ENDs in . or .., then it must get a trailing slash.
    // however, if it ends in anything else non-slashy,
    // then it must NOT get a trailing slash.
    var last = srcPath.slice(-1)[0];
    var hasTrailingSlash = (
        (result.host || relative.host) && (last === '.' || last === '..') ||
        last === '');
  
    // strip single dots, resolve double dots to parent dir
    // if the path tries to go above the root, `up` ends up > 0
    var up = 0;
    for (var i = srcPath.length; i >= 0; i--) {
      last = srcPath[i];
      if (last == '.') {
        srcPath.splice(i, 1);
      } else if (last === '..') {
        srcPath.splice(i, 1);
        up++;
      } else if (up) {
        srcPath.splice(i, 1);
        up--;
      }
    }
  
    // if the path is allowed to go above the root, restore leading ..s
    if (!mustEndAbs && !removeAllDots) {
      for (; up--; up) {
        srcPath.unshift('..');
      }
    }
  
    if (mustEndAbs && srcPath[0] !== '' &&
        (!srcPath[0] || srcPath[0].charAt(0) !== '/')) {
      srcPath.unshift('');
    }
  
    if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) {
      srcPath.push('');
    }
  
    var isAbsolute = srcPath[0] === '' ||
        (srcPath[0] && srcPath[0].charAt(0) === '/');
  
    // put the host back
    if (psychotic) {
      result.hostname = result.host = isAbsolute ? '' :
                                      srcPath.length ? srcPath.shift() : '';
      //occationaly the auth can get stuck only in host
      //this especialy happens in cases like
      //url.resolveObject('mailto:local1@domain1', 'local2@domain2')
      var authInHost = result.host && result.host.indexOf('@') > 0 ?
                       result.host.split('@') : false;
      if (authInHost) {
        result.auth = authInHost.shift();
        result.host = result.hostname = authInHost.shift();
      }
    }
  
    mustEndAbs = mustEndAbs || (result.host && srcPath.length);
  
    if (mustEndAbs && !isAbsolute) {
      srcPath.unshift('');
    }
  
    if (!srcPath.length) {
      result.pathname = null;
      result.path = null;
    } else {
      result.pathname = srcPath.join('/');
    }
  
    //to support request.http
    if (!isNull(result.pathname) || !isNull(result.search)) {
      result.path = (result.pathname ? result.pathname : '') +
                    (result.search ? result.search : '');
    }
    result.auth = relative.auth || result.auth;
    result.slashes = result.slashes || relative.slashes;
    result.href = result.format();
    return result;
  };
  
  Url.prototype.parseHost = function() {
    var host = this.host;
    var port = portPattern.exec(host);
    if (port) {
      port = port[0];
      if (port !== ':') {
        this.port = port.substr(1);
      }
      host = host.substr(0, host.length - port.length);
    }
    if (host) this.hostname = host;
  };
  
  function isString(arg) {
    return typeof arg === "string";
  }
  
  function isObject(arg) {
    return typeof arg === 'object' && arg !== null;
  }
  
  function isNull(arg) {
    return arg === null;
  }
  function isNullOrUndefined(arg) {
    return  arg == null;
  }
  
  },{"punycode":55,"querystring":58}],73:[function(require,module,exports){
  module.exports = function isBuffer(arg) {
    return arg && typeof arg === 'object'
      && typeof arg.copy === 'function'
      && typeof arg.fill === 'function'
      && typeof arg.readUInt8 === 'function';
  }
  },{}],74:[function(require,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 = require('./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 = require('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,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  },{"./support/isBuffer":73,"_process":54,"inherits":52}],75:[function(require,module,exports){
  /*
   *  Copyright 2011 Twitter, Inc.
   *  Licensed under the Apache License, Version 2.0 (the "License");
   *  you may not use this file except in compliance with the License.
   *  You may obtain a copy of the License at
   *
   *  http://www.apache.org/licenses/LICENSE-2.0
   *
   *  Unless required by applicable law or agreed to in writing, software
   *  distributed under the License is distributed on an "AS IS" BASIS,
   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *  See the License for the specific language governing permissions and
   *  limitations under the License.
   */
  
  (function (Hogan) {
    // Setup regex  assignments
    // remove whitespace according to Mustache spec
    var rIsWhitespace = /\S/,
        rQuot = /\"/g,
        rNewline =  /\n/g,
        rCr = /\r/g,
        rSlash = /\\/g,
        tagTypes = {
          '#': 1, '^': 2, '/': 3,  '!': 4, '>': 5,
          '<': 6, '=': 7, '_v': 8, '{': 9, '&': 10
        };
  
    Hogan.scan = function scan(text, delimiters) {
      var len = text.length,
          IN_TEXT = 0,
          IN_TAG_TYPE = 1,
          IN_TAG = 2,
          state = IN_TEXT,
          tagType = null,
          tag = null,
          buf = '',
          tokens = [],
          seenTag = false,
          i = 0,
          lineStart = 0,
          otag = '{{',
          ctag = '}}';
  
      function addBuf() {
        if (buf.length > 0) {
          tokens.push(new String(buf));
          buf = '';
        }
      }
  
      function lineIsWhitespace() {
        var isAllWhitespace = true;
        for (var j = lineStart; j < tokens.length; j++) {
          isAllWhitespace =
            (tokens[j].tag && tagTypes[tokens[j].tag] < tagTypes['_v']) ||
            (!tokens[j].tag && tokens[j].match(rIsWhitespace) === null);
          if (!isAllWhitespace) {
            return false;
          }
        }
  
        return isAllWhitespace;
      }
  
      function filterLine(haveSeenTag, noNewLine) {
        addBuf();
  
        if (haveSeenTag && lineIsWhitespace()) {
          for (var j = lineStart, next; j < tokens.length; j++) {
            if (!tokens[j].tag) {
              if ((next = tokens[j+1]) && next.tag == '>') {
                // set indent to token value
                next.indent = tokens[j].toString()
              }
              tokens.splice(j, 1);
            }
          }
        } else if (!noNewLine) {
          tokens.push({tag:'\n'});
        }
  
        seenTag = false;
        lineStart = tokens.length;
      }
  
      function changeDelimiters(text, index) {
        var close = '=' + ctag,
            closeIndex = text.indexOf(close, index),
            delimiters = trim(
              text.substring(text.indexOf('=', index) + 1, closeIndex)
            ).split(' ');
  
        otag = delimiters[0];
        ctag = delimiters[1];
  
        return closeIndex + close.length - 1;
      }
  
      if (delimiters) {
        delimiters = delimiters.split(' ');
        otag = delimiters[0];
        ctag = delimiters[1];
      }
  
      for (i = 0; i < len; i++) {
        if (state == IN_TEXT) {
          if (tagChange(otag, text, i)) {
            --i;
            addBuf();
            state = IN_TAG_TYPE;
          } else {
            if (text.charAt(i) == '\n') {
              filterLine(seenTag);
            } else {
              buf += text.charAt(i);
            }
          }
        } else if (state == IN_TAG_TYPE) {
          i += otag.length - 1;
          tag = tagTypes[text.charAt(i + 1)];
          tagType = tag ? text.charAt(i + 1) : '_v';
          if (tagType == '=') {
            i = changeDelimiters(text, i);
            state = IN_TEXT;
          } else {
            if (tag) {
              i++;
            }
            state = IN_TAG;
          }
          seenTag = i;
        } else {
          if (tagChange(ctag, text, i)) {
            tokens.push({tag: tagType, n: trim(buf), otag: otag, ctag: ctag,
                         i: (tagType == '/') ? seenTag - ctag.length : i + otag.length});
            buf = '';
            i += ctag.length - 1;
            state = IN_TEXT;
            if (tagType == '{') {
              if (ctag == '}}') {
                i++;
              } else {
                cleanTripleStache(tokens[tokens.length - 1]);
              }
            }
          } else {
            buf += text.charAt(i);
          }
        }
      }
  
      filterLine(seenTag, true);
  
      return tokens;
    }
  
    function cleanTripleStache(token) {
      if (token.n.substr(token.n.length - 1) === '}') {
        token.n = token.n.substring(0, token.n.length - 1);
      }
    }
  
    function trim(s) {
      if (s.trim) {
        return s.trim();
      }
  
      return s.replace(/^\s*|\s*$/g, '');
    }
  
    function tagChange(tag, text, index) {
      if (text.charAt(index) != tag.charAt(0)) {
        return false;
      }
  
      for (var i = 1, l = tag.length; i < l; i++) {
        if (text.charAt(index + i) != tag.charAt(i)) {
          return false;
        }
      }
  
      return true;
    }
  
    function buildTree(tokens, kind, stack, customTags) {
      var instructions = [],
          opener = null,
          token = null;
  
      while (tokens.length > 0) {
        token = tokens.shift();
        if (token.tag == '#' || token.tag == '^' || isOpener(token, customTags)) {
          stack.push(token);
          token.nodes = buildTree(tokens, token.tag, stack, customTags);
          instructions.push(token);
        } else if (token.tag == '/') {
          if (stack.length === 0) {
            throw new Error('Closing tag without opener: /' + token.n);
          }
          opener = stack.pop();
          if (token.n != opener.n && !isCloser(token.n, opener.n, customTags)) {
            throw new Error('Nesting error: ' + opener.n + ' vs. ' + token.n);
          }
          opener.end = token.i;
          return instructions;
        } else {
          instructions.push(token);
        }
      }
  
      if (stack.length > 0) {
        throw new Error('missing closing tag: ' + stack.pop().n);
      }
  
      return instructions;
    }
  
    function isOpener(token, tags) {
      for (var i = 0, l = tags.length; i < l; i++) {
        if (tags[i].o == token.n) {
          token.tag = '#';
          return true;
        }
      }
    }
  
    function isCloser(close, open, tags) {
      for (var i = 0, l = tags.length; i < l; i++) {
        if (tags[i].c == close && tags[i].o == open) {
          return true;
        }
      }
    }
  
    Hogan.generate = function (tree, text, options) {
      var code = 'var _=this;_.b(i=i||"");' + walk(tree) + 'return _.fl();';
      if (options.asString) {
        return 'function(c,p,i){' + code + ';}';
      }
  
      return new Hogan.Template(new Function('c', 'p', 'i', code), text, Hogan, options);
    }
  
    function esc(s) {
      return s.replace(rSlash, '\\\\')
              .replace(rQuot, '\\\"')
              .replace(rNewline, '\\n')
              .replace(rCr, '\\r');
    }
  
    function chooseMethod(s) {
      return (~s.indexOf('.')) ? 'd' : 'f';
    }
  
    function walk(tree) {
      var code = '';
      for (var i = 0, l = tree.length; i < l; i++) {
        var tag = tree[i].tag;
        if (tag == '#') {
          code += section(tree[i].nodes, tree[i].n, chooseMethod(tree[i].n),
                          tree[i].i, tree[i].end, tree[i].otag + " " + tree[i].ctag);
        } else if (tag == '^') {
          code += invertedSection(tree[i].nodes, tree[i].n,
                                  chooseMethod(tree[i].n));
        } else if (tag == '<' || tag == '>') {
          code += partial(tree[i]);
        } else if (tag == '{' || tag == '&') {
          code += tripleStache(tree[i].n, chooseMethod(tree[i].n));
        } else if (tag == '\n') {
          code += text('"\\n"' + (tree.length-1 == i ? '' : ' + i'));
        } else if (tag == '_v') {
          code += variable(tree[i].n, chooseMethod(tree[i].n));
        } else if (tag === undefined) {
          code += text('"' + esc(tree[i]) + '"');
        }
      }
      return code;
    }
  
    function section(nodes, id, method, start, end, tags) {
      return 'if(_.s(_.' + method + '("' + esc(id) + '",c,p,1),' +
             'c,p,0,' + start + ',' + end + ',"' + tags + '")){' +
             '_.rs(c,p,' +
             'function(c,p,_){' +
             walk(nodes) +
             '});c.pop();}';
    }
  
    function invertedSection(nodes, id, method) {
      return 'if(!_.s(_.' + method + '("' + esc(id) + '",c,p,1),c,p,1,0,0,"")){' +
             walk(nodes) +
             '};';
    }
  
    function partial(tok) {
      return '_.b(_.rp("' +  esc(tok.n) + '",c,p,"' + (tok.indent || '') + '"));';
    }
  
    function tripleStache(id, method) {
      return '_.b(_.t(_.' + method + '("' + esc(id) + '",c,p,0)));';
    }
  
    function variable(id, method) {
      return '_.b(_.v(_.' + method + '("' + esc(id) + '",c,p,0)));';
    }
  
    function text(id) {
      return '_.b(' + id + ');';
    }
  
    Hogan.parse = function(tokens, text, options) {
      options = options || {};
      return buildTree(tokens, '', [], options.sectionTags || []);
    },
  
    Hogan.cache = {};
  
    Hogan.compile = function(text, options) {
      // options
      //
      // asString: false (default)
      //
      // sectionTags: [{o: '_foo', c: 'foo'}]
      // An array of object with o and c fields that indicate names for custom
      // section tags. The example above allows parsing of {{_foo}}{{/foo}}.
      //
      // delimiters: A string that overrides the default delimiters.
      // Example: "<% %>"
      //
      options = options || {};
  
      var key = text + '||' + !!options.asString;
  
      var t = this.cache[key];
  
      if (t) {
        return t;
      }
  
      t = this.generate(this.parse(this.scan(text, options.delimiters), text, options), text, options);
      return this.cache[key] = t;
    };
  })(typeof exports !== 'undefined' ? exports : Hogan);
  
  },{}],76:[function(require,module,exports){
  /*
   *  Copyright 2011 Twitter, Inc.
   *  Licensed under the Apache License, Version 2.0 (the "License");
   *  you may not use this file except in compliance with the License.
   *  You may obtain a copy of the License at
   *
   *  http://www.apache.org/licenses/LICENSE-2.0
   *
   *  Unless required by applicable law or agreed to in writing, software
   *  distributed under the License is distributed on an "AS IS" BASIS,
   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *  See the License for the specific language governing permissions and
   *  limitations under the License.
   */
  
  // This file is for use with Node.js. See dist/ for browser files.
  
  var Hogan = require('./compiler');
  Hogan.Template = require('./template').Template;
  module.exports = Hogan; 
  },{"./compiler":75,"./template":77}],77:[function(require,module,exports){
  /*
   *  Copyright 2011 Twitter, Inc.
   *  Licensed under the Apache License, Version 2.0 (the "License");
   *  you may not use this file except in compliance with the License.
   *  You may obtain a copy of the License at
   *
   *  http://www.apache.org/licenses/LICENSE-2.0
   *
   *  Unless required by applicable law or agreed to in writing, software
   *  distributed under the License is distributed on an "AS IS" BASIS,
   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *  See the License for the specific language governing permissions and
   *  limitations under the License.
   */
  
  var Hogan = {};
  
  (function (Hogan, useArrayBuffer) {
    Hogan.Template = function (renderFunc, text, compiler, options) {
      this.r = renderFunc || this.r;
      this.c = compiler;
      this.options = options;
      this.text = text || '';
      this.buf = (useArrayBuffer) ? [] : '';
    }
  
    Hogan.Template.prototype = {
      // render: replaced by generated code.
      r: function (context, partials, indent) { return ''; },
  
      // variable escaping
      v: hoganEscape,
  
      // triple stache
      t: coerceToString,
  
      render: function render(context, partials, indent) {
        return this.ri([context], partials || {}, indent);
      },
  
      // render internal -- a hook for overrides that catches partials too
      ri: function (context, partials, indent) {
        return this.r(context, partials, indent);
      },
  
      // tries to find a partial in the curent scope and render it
      rp: function(name, context, partials, indent) {
        var partial = partials[name];
  
        if (!partial) {
          return '';
        }
  
        if (this.c && typeof partial == 'string') {
          partial = this.c.compile(partial, this.options);
        }
  
        return partial.ri(context, partials, indent);
      },
  
      // render a section
      rs: function(context, partials, section) {
        var tail = context[context.length - 1];
  
        if (!isArray(tail)) {
          section(context, partials, this);
          return;
        }
  
        for (var i = 0; i < tail.length; i++) {
          context.push(tail[i]);
          section(context, partials, this);
          context.pop();
        }
      },
  
      // maybe start a section
      s: function(val, ctx, partials, inverted, start, end, tags) {
        var pass;
  
        if (isArray(val) && val.length === 0) {
          return false;
        }
  
        if (typeof val == 'function') {
          val = this.ls(val, ctx, partials, inverted, start, end, tags);
        }
  
        pass = (val === '') || !!val;
  
        if (!inverted && pass && ctx) {
          ctx.push((typeof val == 'object') ? val : ctx[ctx.length - 1]);
        }
  
        return pass;
      },
  
      // find values with dotted names
      d: function(key, ctx, partials, returnFound) {
        var names = key.split('.'),
            val = this.f(names[0], ctx, partials, returnFound),
            cx = null;
  
        if (key === '.' && isArray(ctx[ctx.length - 2])) {
          return ctx[ctx.length - 1];
        }
  
        for (var i = 1; i < names.length; i++) {
          if (val && typeof val == 'object' && names[i] in val) {
            cx = val;
            val = val[names[i]];
          } else {
            val = '';
          }
        }
  
        if (returnFound && !val) {
          return false;
        }
  
        if (!returnFound && typeof val == 'function') {
          ctx.push(cx);
          val = this.lv(val, ctx, partials);
          ctx.pop();
        }
  
        return val;
      },
  
      // find values with normal names
      f: function(key, ctx, partials, returnFound) {
        var val = false,
            v = null,
            found = false;
  
        for (var i = ctx.length - 1; i >= 0; i--) {
          v = ctx[i];
          if (v && typeof v == 'object' && key in v) {
            val = v[key];
            found = true;
            break;
          }
        }
  
        if (!found) {
          return (returnFound) ? false : "";
        }
  
        if (!returnFound && typeof val == 'function') {
          val = this.lv(val, ctx, partials);
        }
  
        return val;
      },
  
      // higher order templates
      ho: function(val, cx, partials, text, tags) {
        var compiler = this.c;
        var options = this.options;
        options.delimiters = tags;
        var text = val.call(cx, text);
        text = (text == null) ? String(text) : text.toString();
        this.b(compiler.compile(text, options).render(cx, partials));
        return false;
      },
  
      // template result buffering
      b: (useArrayBuffer) ? function(s) { this.buf.push(s); } :
                            function(s) { this.buf += s; },
      fl: (useArrayBuffer) ? function() { var r = this.buf.join(''); this.buf = []; return r; } :
                             function() { var r = this.buf; this.buf = ''; return r; },
  
      // lambda replace section
      ls: function(val, ctx, partials, inverted, start, end, tags) {
        var cx = ctx[ctx.length - 1],
            t = null;
  
        if (!inverted && this.c && val.length > 0) {
          return this.ho(val, cx, partials, this.text.substring(start, end), tags);
        }
  
        t = val.call(cx);
  
        if (typeof t == 'function') {
          if (inverted) {
            return true;
          } else if (this.c) {
            return this.ho(t, cx, partials, this.text.substring(start, end), tags);
          }
        }
  
        return t;
      },
  
      // lambda replace variable
      lv: function(val, ctx, partials) {
        var cx = ctx[ctx.length - 1];
        var result = val.call(cx);
  
        if (typeof result == 'function') {
          result = coerceToString(result.call(cx));
          if (this.c && ~result.indexOf("{\u007B")) {
            return this.c.compile(result, this.options).render(cx, partials);
          }
        }
  
        return coerceToString(result);
      }
  
    };
  
    var rAmp = /&/g,
        rLt = /</g,
        rGt = />/g,
        rApos =/\'/g,
        rQuot = /\"/g,
        hChars =/[&<>\"\']/;
  
  
    function coerceToString(val) {
      return String((val === null || val === undefined) ? '' : val);
    }
  
    function hoganEscape(str) {
      str = coerceToString(str);
      return hChars.test(str) ?
        str
          .replace(rAmp,'&amp;')
          .replace(rLt,'&lt;')
          .replace(rGt,'&gt;')
          .replace(rApos,'&#39;')
          .replace(rQuot, '&quot;') :
        str;
    }
  
    var isArray = Array.isArray || function(a) {
      return Object.prototype.toString.call(a) === '[object Array]';
    };
  
  })(typeof exports !== 'undefined' ? exports : Hogan);
  
  
  },{}],78:[function(require,module,exports){
  (function (module){
      "use strict";
  
      /*The following is the data format of a cache element
       name        : Name of the dependency
       singleton   : true/false
       fn          : Function constructor, can be a prototype or function.
       deps        : Array of dependencies where the names correspond to other named dependencies
       instance    : The instance of an element, can be pre constructed and passed in or constructed by fn.
       */
  
      var isArray = function isArray(o) { return Object.prototype.toString.call(o) === '[object Array]'; };
      var isString = function isString(s) { return Object.prototype.toString.call(s) === '[object String]'; };
      var isNull = function isNull(n) { return Object.prototype.toString.call(n) === '[object Null]'; };
      var isUndefined = function isUndefined(u) { return Object.prototype.toString.call(u) === '[object Undefined]'; };
      var isObject = function isObject(o) { return Object.prototype.toString.call(o) === '[object Object]'; };
  
      function factory (type){
          if (isString(type)){
              return type;
          }
          else if (isArray(type)){
              return type;
          }
          else {
              var tmp = function (args) {
                  return type.apply(this, args);
              };
              // -- Newer browsers have a safer method of inheritance; sorry IE*.
              if ('create' in Object){
                  tmp.prototype = Object.create(type.prototype, {
                      constructor: {
                          value: tmp,
                          enumerable : false,
                          writable: true,
                          configurable: true
                      }
                  });
              }
              else { tmp.prototype = type.prototype; }
              return tmp;
          }
      };
      function addCategory(categories, category, name){
          (category in categories) ?
              (categories[category].push(name)) :
              (categories[category] = [name]);
      };
      function wrap(name){
          return function (obj) {
              return obj[name];
          };
      };
      function wrapGlobal(obj){
          return function (){
              return obj;
          };
      };
  
      var Nodeject = function Nodeject(options){
          this.config = options;
          this.cache = {};
          this.categories = {};
  
          // -- Create global default of Singleton
          this.singleton = (!!options && !!options.singleton) ? options.singleton : false;
      };
  
      Nodeject.prototype.define = function (options){
          if (!(options.name)){ throw "Name is not found or is empty as part of the definition."; }
          //if (!options.type){ throw "Type isn't found or is empty as part of the definition."; }
  
          if (!('name' in this.cache)){
              if ('wrap' in options){
                  var obj = options.wrap;
                  var opts = {
                      name : options.name,
                      type : (obj.context ? wrap : wrapGlobal).call(this, obj.resolve),
                      singleton : (!!options.singleton) ? options.singleton : this.singleton,
                      deps : [obj.context]
                  };
                  if (isUndefined(obj.context)) delete opts.deps;
                  return this.define(opts);
              }else{
                  if (isNull(options.type) || isUndefined(options.type)){
                      this.cache[options.name] = {
                          singleton : this.singleton,
                          isEmpty : true,
                          instance : options.type
                      };
                      return this;
                  }
  
                  this.cache[options.name] = {
                      singleton   : options.singleton || this.singleton,
                      fn          : factory(options.type),
                      deps        : options.deps || [],
                      instance    : null,
                      requiresNew : !(isString(options.type) || isArray(options.type))
                  };
  
                  if (options.category){
                      var arr = options.category || [];
                      if (isArray(arr)){
                          for (var i = 0; i < arr.length; i = i + 1){
                              addCategory(this.categories, arr[i], options.name);
                          }
                      }
                      else {
                          addCategory(this.categories, arr, options.name);
                      }
                  }
              }
          }
          else { throw "Type or type name already defined in the container."; }
  
          return this;
      };
  
      Nodeject.prototype.resolve = function (options){
          var name = '', category = '', singleton = this.singleton;
  
          // -- Marshall incoming parameters to resolve the type.
          if (isString(options)){ name = options; }
          else if(options.name){ name = options.name || ''; }
          else if (options.category && isString(options.category)) { category = options.category; }
          else { throw "Cannot resolve"; }
  
          if (name in this.cache && this.cache[name].isEmpty){
              return this.cache[name].instance;
          }
  
  
          var deps, i;
          if (name in this.cache){
              var type = this.cache[name];
              singleton = options.singleton || type.singleton || this.singleton;
  
              // Resolve dependencies.
              deps = [];
              for(i = 0; i < type.deps.length; i = i + 1){
                  var subtype = this.resolve(type.deps[i]);
                  deps.push(subtype);
              }
  
              if (singleton){
                  type.instance = type.instance || (type.requiresNew ? new type.fn(deps) : type.fn);
                  return type.instance;
              }
  
              return type.requiresNew ? new type.fn(deps) : type.fn;
          }
          else if (category in this.categories){
              var types = this.categories[category] || [];
              var format = options.format || 'array';
              if (format === 'literal'){
                  deps = {};
                  for (i = 0; i < types.length; i = i + 1){
                      deps[types[i]] = this.resolve(types[i]);
                  }
              }
              else {
                  deps = [];
                  for(i = 0; i < types.length; i = i + 1){
                      deps.push(this.resolve(types[i]));
                  }
              }
              return deps;
          }
          else {
              throw "The type '" + name + "' is not configured in the container.";
          }
      };
  
  
  
      module.exports = Nodeject;
  
  })(module)
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  },{}],79:[function(require,module,exports){
  //     Underscore.js 1.7.0
  //     http://underscorejs.org
  //     (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
  //     Underscore may be freely distributed under the MIT license.
  
  (function() {
  
    // Baseline setup
    // --------------
  
    // Establish the root object, `window` in the browser, or `exports` on the server.
    var root = this;
  
    // Save the previous value of the `_` variable.
    var previousUnderscore = root._;
  
    // Save bytes in the minified (but not gzipped) version:
    var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
  
    // Create quick reference variables for speed access to core prototypes.
    var
      push             = ArrayProto.push,
      slice            = ArrayProto.slice,
      concat           = ArrayProto.concat,
      toString         = ObjProto.toString,
      hasOwnProperty   = ObjProto.hasOwnProperty;
  
    // All **ECMAScript 5** native function implementations that we hope to use
    // are declared here.
    var
      nativeIsArray      = Array.isArray,
      nativeKeys         = Object.keys,
      nativeBind         = FuncProto.bind;
  
    // Create a safe reference to the Underscore object for use below.
    var _ = function(obj) {
      if (obj instanceof _) return obj;
      if (!(this instanceof _)) return new _(obj);
      this._wrapped = obj;
    };
  
    // Export the Underscore object for **Node.js**, with
    // backwards-compatibility for the old `require()` API. If we're in
    // the browser, add `_` as a global object.
    if (typeof exports !== 'undefined') {
      if (typeof module !== 'undefined' && module.exports) {
        exports = module.exports = _;
      }
      exports._ = _;
    } else {
      root._ = _;
    }
  
    // Current version.
    _.VERSION = '1.7.0';
  
    // Internal function that returns an efficient (for current engines) version
    // of the passed-in callback, to be repeatedly applied in other Underscore
    // functions.
    var createCallback = function(func, context, argCount) {
      if (context === void 0) return func;
      switch (argCount == null ? 3 : argCount) {
        case 1: return function(value) {
          return func.call(context, value);
        };
        case 2: return function(value, other) {
          return func.call(context, value, other);
        };
        case 3: return function(value, index, collection) {
          return func.call(context, value, index, collection);
        };
        case 4: return function(accumulator, value, index, collection) {
          return func.call(context, accumulator, value, index, collection);
        };
      }
      return function() {
        return func.apply(context, arguments);
      };
    };
  
    // A mostly-internal function to generate callbacks that can be applied
    // to each element in a collection, returning the desired result — either
    // identity, an arbitrary callback, a property matcher, or a property accessor.
    _.iteratee = function(value, context, argCount) {
      if (value == null) return _.identity;
      if (_.isFunction(value)) return createCallback(value, context, argCount);
      if (_.isObject(value)) return _.matches(value);
      return _.property(value);
    };
  
    // Collection Functions
    // --------------------
  
    // The cornerstone, an `each` implementation, aka `forEach`.
    // Handles raw objects in addition to array-likes. Treats all
    // sparse array-likes as if they were dense.
    _.each = _.forEach = function(obj, iteratee, context) {
      if (obj == null) return obj;
      iteratee = createCallback(iteratee, context);
      var i, length = obj.length;
      if (length === +length) {
        for (i = 0; i < length; i++) {
          iteratee(obj[i], i, obj);
        }
      } else {
        var keys = _.keys(obj);
        for (i = 0, length = keys.length; i < length; i++) {
          iteratee(obj[keys[i]], keys[i], obj);
        }
      }
      return obj;
    };
  
    // Return the results of applying the iteratee to each element.
    _.map = _.collect = function(obj, iteratee, context) {
      if (obj == null) return [];
      iteratee = _.iteratee(iteratee, context);
      var keys = obj.length !== +obj.length && _.keys(obj),
          length = (keys || obj).length,
          results = Array(length),
          currentKey;
      for (var index = 0; index < length; index++) {
        currentKey = keys ? keys[index] : index;
        results[index] = iteratee(obj[currentKey], currentKey, obj);
      }
      return results;
    };
  
    var reduceError = 'Reduce of empty array with no initial value';
  
    // **Reduce** builds up a single result from a list of values, aka `inject`,
    // or `foldl`.
    _.reduce = _.foldl = _.inject = function(obj, iteratee, memo, context) {
      if (obj == null) obj = [];
      iteratee = createCallback(iteratee, context, 4);
      var keys = obj.length !== +obj.length && _.keys(obj),
          length = (keys || obj).length,
          index = 0, currentKey;
      if (arguments.length < 3) {
        if (!length) throw new TypeError(reduceError);
        memo = obj[keys ? keys[index++] : index++];
      }
      for (; index < length; index++) {
        currentKey = keys ? keys[index] : index;
        memo = iteratee(memo, obj[currentKey], currentKey, obj);
      }
      return memo;
    };
  
    // The right-associative version of reduce, also known as `foldr`.
    _.reduceRight = _.foldr = function(obj, iteratee, memo, context) {
      if (obj == null) obj = [];
      iteratee = createCallback(iteratee, context, 4);
      var keys = obj.length !== + obj.length && _.keys(obj),
          index = (keys || obj).length,
          currentKey;
      if (arguments.length < 3) {
        if (!index) throw new TypeError(reduceError);
        memo = obj[keys ? keys[--index] : --index];
      }
      while (index--) {
        currentKey = keys ? keys[index] : index;
        memo = iteratee(memo, obj[currentKey], currentKey, obj);
      }
      return memo;
    };
  
    // Return the first value which passes a truth test. Aliased as `detect`.
    _.find = _.detect = function(obj, predicate, context) {
      var result;
      predicate = _.iteratee(predicate, context);
      _.some(obj, function(value, index, list) {
        if (predicate(value, index, list)) {
          result = value;
          return true;
        }
      });
      return result;
    };
  
    // Return all the elements that pass a truth test.
    // Aliased as `select`.
    _.filter = _.select = function(obj, predicate, context) {
      var results = [];
      if (obj == null) return results;
      predicate = _.iteratee(predicate, context);
      _.each(obj, function(value, index, list) {
        if (predicate(value, index, list)) results.push(value);
      });
      return results;
    };
  
    // Return all the elements for which a truth test fails.
    _.reject = function(obj, predicate, context) {
      return _.filter(obj, _.negate(_.iteratee(predicate)), context);
    };
  
    // Determine whether all of the elements match a truth test.
    // Aliased as `all`.
    _.every = _.all = function(obj, predicate, context) {
      if (obj == null) return true;
      predicate = _.iteratee(predicate, context);
      var keys = obj.length !== +obj.length && _.keys(obj),
          length = (keys || obj).length,
          index, currentKey;
      for (index = 0; index < length; index++) {
        currentKey = keys ? keys[index] : index;
        if (!predicate(obj[currentKey], currentKey, obj)) return false;
      }
      return true;
    };
  
    // Determine if at least one element in the object matches a truth test.
    // Aliased as `any`.
    _.some = _.any = function(obj, predicate, context) {
      if (obj == null) return false;
      predicate = _.iteratee(predicate, context);
      var keys = obj.length !== +obj.length && _.keys(obj),
          length = (keys || obj).length,
          index, currentKey;
      for (index = 0; index < length; index++) {
        currentKey = keys ? keys[index] : index;
        if (predicate(obj[currentKey], currentKey, obj)) return true;
      }
      return false;
    };
  
    // Determine if the array or object contains a given value (using `===`).
    // Aliased as `include`.
    _.contains = _.include = function(obj, target) {
      if (obj == null) return false;
      if (obj.length !== +obj.length) obj = _.values(obj);
      return _.indexOf(obj, target) >= 0;
    };
  
    // Invoke a method (with arguments) on every item in a collection.
    _.invoke = function(obj, method) {
      var args = slice.call(arguments, 2);
      var isFunc = _.isFunction(method);
      return _.map(obj, function(value) {
        return (isFunc ? method : value[method]).apply(value, args);
      });
    };
  
    // Convenience version of a common use case of `map`: fetching a property.
    _.pluck = function(obj, key) {
      return _.map(obj, _.property(key));
    };
  
    // Convenience version of a common use case of `filter`: selecting only objects
    // containing specific `key:value` pairs.
    _.where = function(obj, attrs) {
      return _.filter(obj, _.matches(attrs));
    };
  
    // Convenience version of a common use case of `find`: getting the first object
    // containing specific `key:value` pairs.
    _.findWhere = function(obj, attrs) {
      return _.find(obj, _.matches(attrs));
    };
  
    // Return the maximum element (or element-based computation).
    _.max = function(obj, iteratee, context) {
      var result = -Infinity, lastComputed = -Infinity,
          value, computed;
      if (iteratee == null && obj != null) {
        obj = obj.length === +obj.length ? obj : _.values(obj);
        for (var i = 0, length = obj.length; i < length; i++) {
          value = obj[i];
          if (value > result) {
            result = value;
          }
        }
      } else {
        iteratee = _.iteratee(iteratee, context);
        _.each(obj, function(value, index, list) {
          computed = iteratee(value, index, list);
          if (computed > lastComputed || computed === -Infinity && result === -Infinity) {
            result = value;
            lastComputed = computed;
          }
        });
      }
      return result;
    };
  
    // Return the minimum element (or element-based computation).
    _.min = function(obj, iteratee, context) {
      var result = Infinity, lastComputed = Infinity,
          value, computed;
      if (iteratee == null && obj != null) {
        obj = obj.length === +obj.length ? obj : _.values(obj);
        for (var i = 0, length = obj.length; i < length; i++) {
          value = obj[i];
          if (value < result) {
            result = value;
          }
        }
      } else {
        iteratee = _.iteratee(iteratee, context);
        _.each(obj, function(value, index, list) {
          computed = iteratee(value, index, list);
          if (computed < lastComputed || computed === Infinity && result === Infinity) {
            result = value;
            lastComputed = computed;
          }
        });
      }
      return result;
    };
  
    // Shuffle a collection, using the modern version of the
    // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
    _.shuffle = function(obj) {
      var set = obj && obj.length === +obj.length ? obj : _.values(obj);
      var length = set.length;
      var shuffled = Array(length);
      for (var index = 0, rand; index < length; index++) {
        rand = _.random(0, index);
        if (rand !== index) shuffled[index] = shuffled[rand];
        shuffled[rand] = set[index];
      }
      return shuffled;
    };
  
    // Sample **n** random values from a collection.
    // If **n** is not specified, returns a single random element.
    // The internal `guard` argument allows it to work with `map`.
    _.sample = function(obj, n, guard) {
      if (n == null || guard) {
        if (obj.length !== +obj.length) obj = _.values(obj);
        return obj[_.random(obj.length - 1)];
      }
      return _.shuffle(obj).slice(0, Math.max(0, n));
    };
  
    // Sort the object's values by a criterion produced by an iteratee.
    _.sortBy = function(obj, iteratee, context) {
      iteratee = _.iteratee(iteratee, context);
      return _.pluck(_.map(obj, function(value, index, list) {
        return {
          value: value,
          index: index,
          criteria: iteratee(value, index, list)
        };
      }).sort(function(left, right) {
        var a = left.criteria;
        var b = right.criteria;
        if (a !== b) {
          if (a > b || a === void 0) return 1;
          if (a < b || b === void 0) return -1;
        }
        return left.index - right.index;
      }), 'value');
    };
  
    // An internal function used for aggregate "group by" operations.
    var group = function(behavior) {
      return function(obj, iteratee, context) {
        var result = {};
        iteratee = _.iteratee(iteratee, context);
        _.each(obj, function(value, index) {
          var key = iteratee(value, index, obj);
          behavior(result, value, key);
        });
        return result;
      };
    };
  
    // Groups the object's values by a criterion. Pass either a string attribute
    // to group by, or a function that returns the criterion.
    _.groupBy = group(function(result, value, key) {
      if (_.has(result, key)) result[key].push(value); else result[key] = [value];
    });
  
    // Indexes the object's values by a criterion, similar to `groupBy`, but for
    // when you know that your index values will be unique.
    _.indexBy = group(function(result, value, key) {
      result[key] = value;
    });
  
    // Counts instances of an object that group by a certain criterion. Pass
    // either a string attribute to count by, or a function that returns the
    // criterion.
    _.countBy = group(function(result, value, key) {
      if (_.has(result, key)) result[key]++; else result[key] = 1;
    });
  
    // Use a comparator function to figure out the smallest index at which
    // an object should be inserted so as to maintain order. Uses binary search.
    _.sortedIndex = function(array, obj, iteratee, context) {
      iteratee = _.iteratee(iteratee, context, 1);
      var value = iteratee(obj);
      var low = 0, high = array.length;
      while (low < high) {
        var mid = low + high >>> 1;
        if (iteratee(array[mid]) < value) low = mid + 1; else high = mid;
      }
      return low;
    };
  
    // Safely create a real, live array from anything iterable.
    _.toArray = function(obj) {
      if (!obj) return [];
      if (_.isArray(obj)) return slice.call(obj);
      if (obj.length === +obj.length) return _.map(obj, _.identity);
      return _.values(obj);
    };
  
    // Return the number of elements in an object.
    _.size = function(obj) {
      if (obj == null) return 0;
      return obj.length === +obj.length ? obj.length : _.keys(obj).length;
    };
  
    // Split a collection into two arrays: one whose elements all satisfy the given
    // predicate, and one whose elements all do not satisfy the predicate.
    _.partition = function(obj, predicate, context) {
      predicate = _.iteratee(predicate, context);
      var pass = [], fail = [];
      _.each(obj, function(value, key, obj) {
        (predicate(value, key, obj) ? pass : fail).push(value);
      });
      return [pass, fail];
    };
  
    // Array Functions
    // ---------------
  
    // Get the first element of an array. Passing **n** will return the first N
    // values in the array. Aliased as `head` and `take`. The **guard** check
    // allows it to work with `_.map`.
    _.first = _.head = _.take = function(array, n, guard) {
      if (array == null) return void 0;
      if (n == null || guard) return array[0];
      if (n < 0) return [];
      return slice.call(array, 0, n);
    };
  
    // Returns everything but the last entry of the array. Especially useful on
    // the arguments object. Passing **n** will return all the values in
    // the array, excluding the last N. The **guard** check allows it to work with
    // `_.map`.
    _.initial = function(array, n, guard) {
      return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n)));
    };
  
    // Get the last element of an array. Passing **n** will return the last N
    // values in the array. The **guard** check allows it to work with `_.map`.
    _.last = function(array, n, guard) {
      if (array == null) return void 0;
      if (n == null || guard) return array[array.length - 1];
      return slice.call(array, Math.max(array.length - n, 0));
    };
  
    // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
    // Especially useful on the arguments object. Passing an **n** will return
    // the rest N values in the array. The **guard**
    // check allows it to work with `_.map`.
    _.rest = _.tail = _.drop = function(array, n, guard) {
      return slice.call(array, n == null || guard ? 1 : n);
    };
  
    // Trim out all falsy values from an array.
    _.compact = function(array) {
      return _.filter(array, _.identity);
    };
  
    // Internal implementation of a recursive `flatten` function.
    var flatten = function(input, shallow, strict, output) {
      if (shallow && _.every(input, _.isArray)) {
        return concat.apply(output, input);
      }
      for (var i = 0, length = input.length; i < length; i++) {
        var value = input[i];
        if (!_.isArray(value) && !_.isArguments(value)) {
          if (!strict) output.push(value);
        } else if (shallow) {
          push.apply(output, value);
        } else {
          flatten(value, shallow, strict, output);
        }
      }
      return output;
    };
  
    // Flatten out an array, either recursively (by default), or just one level.
    _.flatten = function(array, shallow) {
      return flatten(array, shallow, false, []);
    };
  
    // Return a version of the array that does not contain the specified value(s).
    _.without = function(array) {
      return _.difference(array, slice.call(arguments, 1));
    };
  
    // Produce a duplicate-free version of the array. If the array has already
    // been sorted, you have the option of using a faster algorithm.
    // Aliased as `unique`.
    _.uniq = _.unique = function(array, isSorted, iteratee, context) {
      if (array == null) return [];
      if (!_.isBoolean(isSorted)) {
        context = iteratee;
        iteratee = isSorted;
        isSorted = false;
      }
      if (iteratee != null) iteratee = _.iteratee(iteratee, context);
      var result = [];
      var seen = [];
      for (var i = 0, length = array.length; i < length; i++) {
        var value = array[i];
        if (isSorted) {
          if (!i || seen !== value) result.push(value);
          seen = value;
        } else if (iteratee) {
          var computed = iteratee(value, i, array);
          if (_.indexOf(seen, computed) < 0) {
            seen.push(computed);
            result.push(value);
          }
        } else if (_.indexOf(result, value) < 0) {
          result.push(value);
        }
      }
      return result;
    };
  
    // Produce an array that contains the union: each distinct element from all of
    // the passed-in arrays.
    _.union = function() {
      return _.uniq(flatten(arguments, true, true, []));
    };
  
    // Produce an array that contains every item shared between all the
    // passed-in arrays.
    _.intersection = function(array) {
      if (array == null) return [];
      var result = [];
      var argsLength = arguments.length;
      for (var i = 0, length = array.length; i < length; i++) {
        var item = array[i];
        if (_.contains(result, item)) continue;
        for (var j = 1; j < argsLength; j++) {
          if (!_.contains(arguments[j], item)) break;
        }
        if (j === argsLength) result.push(item);
      }
      return result;
    };
  
    // Take the difference between one array and a number of other arrays.
    // Only the elements present in just the first array will remain.
    _.difference = function(array) {
      var rest = flatten(slice.call(arguments, 1), true, true, []);
      return _.filter(array, function(value){
        return !_.contains(rest, value);
      });
    };
  
    // Zip together multiple lists into a single array -- elements that share
    // an index go together.
    _.zip = function(array) {
      if (array == null) return [];
      var length = _.max(arguments, 'length').length;
      var results = Array(length);
      for (var i = 0; i < length; i++) {
        results[i] = _.pluck(arguments, i);
      }
      return results;
    };
  
    // Converts lists into objects. Pass either a single array of `[key, value]`
    // pairs, or two parallel arrays of the same length -- one of keys, and one of
    // the corresponding values.
    _.object = function(list, values) {
      if (list == null) return {};
      var result = {};
      for (var i = 0, length = list.length; i < length; i++) {
        if (values) {
          result[list[i]] = values[i];
        } else {
          result[list[i][0]] = list[i][1];
        }
      }
      return result;
    };
  
    // Return the position of the first occurrence of an item in an array,
    // or -1 if the item is not included in the array.
    // If the array is large and already in sort order, pass `true`
    // for **isSorted** to use binary search.
    _.indexOf = function(array, item, isSorted) {
      if (array == null) return -1;
      var i = 0, length = array.length;
      if (isSorted) {
        if (typeof isSorted == 'number') {
          i = isSorted < 0 ? Math.max(0, length + isSorted) : isSorted;
        } else {
          i = _.sortedIndex(array, item);
          return array[i] === item ? i : -1;
        }
      }
      for (; i < length; i++) if (array[i] === item) return i;
      return -1;
    };
  
    _.lastIndexOf = function(array, item, from) {
      if (array == null) return -1;
      var idx = array.length;
      if (typeof from == 'number') {
        idx = from < 0 ? idx + from + 1 : Math.min(idx, from + 1);
      }
      while (--idx >= 0) if (array[idx] === item) return idx;
      return -1;
    };
  
    // Generate an integer Array containing an arithmetic progression. A port of
    // the native Python `range()` function. See
    // [the Python documentation](http://docs.python.org/library/functions.html#range).
    _.range = function(start, stop, step) {
      if (arguments.length <= 1) {
        stop = start || 0;
        start = 0;
      }
      step = step || 1;
  
      var length = Math.max(Math.ceil((stop - start) / step), 0);
      var range = Array(length);
  
      for (var idx = 0; idx < length; idx++, start += step) {
        range[idx] = start;
      }
  
      return range;
    };
  
    // Function (ahem) Functions
    // ------------------
  
    // Reusable constructor function for prototype setting.
    var Ctor = function(){};
  
    // Create a function bound to a given object (assigning `this`, and arguments,
    // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
    // available.
    _.bind = function(func, context) {
      var args, bound;
      if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
      if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function');
      args = slice.call(arguments, 2);
      bound = function() {
        if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));
        Ctor.prototype = func.prototype;
        var self = new Ctor;
        Ctor.prototype = null;
        var result = func.apply(self, args.concat(slice.call(arguments)));
        if (_.isObject(result)) return result;
        return self;
      };
      return bound;
    };
  
    // Partially apply a function by creating a version that has had some of its
    // arguments pre-filled, without changing its dynamic `this` context. _ acts
    // as a placeholder, allowing any combination of arguments to be pre-filled.
    _.partial = function(func) {
      var boundArgs = slice.call(arguments, 1);
      return function() {
        var position = 0;
        var args = boundArgs.slice();
        for (var i = 0, length = args.length; i < length; i++) {
          if (args[i] === _) args[i] = arguments[position++];
        }
        while (position < arguments.length) args.push(arguments[position++]);
        return func.apply(this, args);
      };
    };
  
    // Bind a number of an object's methods to that object. Remaining arguments
    // are the method names to be bound. Useful for ensuring that all callbacks
    // defined on an object belong to it.
    _.bindAll = function(obj) {
      var i, length = arguments.length, key;
      if (length <= 1) throw new Error('bindAll must be passed function names');
      for (i = 1; i < length; i++) {
        key = arguments[i];
        obj[key] = _.bind(obj[key], obj);
      }
      return obj;
    };
  
    // Memoize an expensive function by storing its results.
    _.memoize = function(func, hasher) {
      var memoize = function(key) {
        var cache = memoize.cache;
        var address = hasher ? hasher.apply(this, arguments) : key;
        if (!_.has(cache, address)) cache[address] = func.apply(this, arguments);
        return cache[address];
      };
      memoize.cache = {};
      return memoize;
    };
  
    // Delays a function for the given number of milliseconds, and then calls
    // it with the arguments supplied.
    _.delay = function(func, wait) {
      var args = slice.call(arguments, 2);
      return setTimeout(function(){
        return func.apply(null, args);
      }, wait);
    };
  
    // Defers a function, scheduling it to run after the current call stack has
    // cleared.
    _.defer = function(func) {
      return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1)));
    };
  
    // Returns a function, that, when invoked, will only be triggered at most once
    // during a given window of time. Normally, the throttled function will run
    // as much as it can, without ever going more than once per `wait` duration;
    // but if you'd like to disable the execution on the leading edge, pass
    // `{leading: false}`. To disable execution on the trailing edge, ditto.
    _.throttle = function(func, wait, options) {
      var context, args, result;
      var timeout = null;
      var previous = 0;
      if (!options) options = {};
      var later = function() {
        previous = options.leading === false ? 0 : _.now();
        timeout = null;
        result = func.apply(context, args);
        if (!timeout) context = args = null;
      };
      return function() {
        var now = _.now();
        if (!previous && options.leading === false) previous = now;
        var remaining = wait - (now - previous);
        context = this;
        args = arguments;
        if (remaining <= 0 || remaining > wait) {
          clearTimeout(timeout);
          timeout = null;
          previous = now;
          result = func.apply(context, args);
          if (!timeout) context = args = null;
        } else if (!timeout && options.trailing !== false) {
          timeout = setTimeout(later, remaining);
        }
        return result;
      };
    };
  
    // Returns a function, that, as long as it continues to be invoked, will not
    // be triggered. The function will be called after it stops being called for
    // N milliseconds. If `immediate` is passed, trigger the function on the
    // leading edge, instead of the trailing.
    _.debounce = function(func, wait, immediate) {
      var timeout, args, context, timestamp, result;
  
      var later = function() {
        var last = _.now() - timestamp;
  
        if (last < wait && last > 0) {
          timeout = setTimeout(later, wait - last);
        } else {
          timeout = null;
          if (!immediate) {
            result = func.apply(context, args);
            if (!timeout) context = args = null;
          }
        }
      };
  
      return function() {
        context = this;
        args = arguments;
        timestamp = _.now();
        var callNow = immediate && !timeout;
        if (!timeout) timeout = setTimeout(later, wait);
        if (callNow) {
          result = func.apply(context, args);
          context = args = null;
        }
  
        return result;
      };
    };
  
    // Returns the first function passed as an argument to the second,
    // allowing you to adjust arguments, run code before and after, and
    // conditionally execute the original function.
    _.wrap = function(func, wrapper) {
      return _.partial(wrapper, func);
    };
  
    // Returns a negated version of the passed-in predicate.
    _.negate = function(predicate) {
      return function() {
        return !predicate.apply(this, arguments);
      };
    };
  
    // Returns a function that is the composition of a list of functions, each
    // consuming the return value of the function that follows.
    _.compose = function() {
      var args = arguments;
      var start = args.length - 1;
      return function() {
        var i = start;
        var result = args[start].apply(this, arguments);
        while (i--) result = args[i].call(this, result);
        return result;
      };
    };
  
    // Returns a function that will only be executed after being called N times.
    _.after = function(times, func) {
      return function() {
        if (--times < 1) {
          return func.apply(this, arguments);
        }
      };
    };
  
    // Returns a function that will only be executed before being called N times.
    _.before = function(times, func) {
      var memo;
      return function() {
        if (--times > 0) {
          memo = func.apply(this, arguments);
        } else {
          func = null;
        }
        return memo;
      };
    };
  
    // Returns a function that will be executed at most one time, no matter how
    // often you call it. Useful for lazy initialization.
    _.once = _.partial(_.before, 2);
  
    // Object Functions
    // ----------------
  
    // Retrieve the names of an object's properties.
    // Delegates to **ECMAScript 5**'s native `Object.keys`
    _.keys = function(obj) {
      if (!_.isObject(obj)) return [];
      if (nativeKeys) return nativeKeys(obj);
      var keys = [];
      for (var key in obj) if (_.has(obj, key)) keys.push(key);
      return keys;
    };
  
    // Retrieve the values of an object's properties.
    _.values = function(obj) {
      var keys = _.keys(obj);
      var length = keys.length;
      var values = Array(length);
      for (var i = 0; i < length; i++) {
        values[i] = obj[keys[i]];
      }
      return values;
    };
  
    // Convert an object into a list of `[key, value]` pairs.
    _.pairs = function(obj) {
      var keys = _.keys(obj);
      var length = keys.length;
      var pairs = Array(length);
      for (var i = 0; i < length; i++) {
        pairs[i] = [keys[i], obj[keys[i]]];
      }
      return pairs;
    };
  
    // Invert the keys and values of an object. The values must be serializable.
    _.invert = function(obj) {
      var result = {};
      var keys = _.keys(obj);
      for (var i = 0, length = keys.length; i < length; i++) {
        result[obj[keys[i]]] = keys[i];
      }
      return result;
    };
  
    // Return a sorted list of the function names available on the object.
    // Aliased as `methods`
    _.functions = _.methods = function(obj) {
      var names = [];
      for (var key in obj) {
        if (_.isFunction(obj[key])) names.push(key);
      }
      return names.sort();
    };
  
    // Extend a given object with all the properties in passed-in object(s).
    _.extend = function(obj) {
      if (!_.isObject(obj)) return obj;
      var source, prop;
      for (var i = 1, length = arguments.length; i < length; i++) {
        source = arguments[i];
        for (prop in source) {
          if (hasOwnProperty.call(source, prop)) {
              obj[prop] = source[prop];
          }
        }
      }
      return obj;
    };
  
    // Return a copy of the object only containing the whitelisted properties.
    _.pick = function(obj, iteratee, context) {
      var result = {}, key;
      if (obj == null) return result;
      if (_.isFunction(iteratee)) {
        iteratee = createCallback(iteratee, context);
        for (key in obj) {
          var value = obj[key];
          if (iteratee(value, key, obj)) result[key] = value;
        }
      } else {
        var keys = concat.apply([], slice.call(arguments, 1));
        obj = new Object(obj);
        for (var i = 0, length = keys.length; i < length; i++) {
          key = keys[i];
          if (key in obj) result[key] = obj[key];
        }
      }
      return result;
    };
  
     // Return a copy of the object without the blacklisted properties.
    _.omit = function(obj, iteratee, context) {
      if (_.isFunction(iteratee)) {
        iteratee = _.negate(iteratee);
      } else {
        var keys = _.map(concat.apply([], slice.call(arguments, 1)), String);
        iteratee = function(value, key) {
          return !_.contains(keys, key);
        };
      }
      return _.pick(obj, iteratee, context);
    };
  
    // Fill in a given object with default properties.
    _.defaults = function(obj) {
      if (!_.isObject(obj)) return obj;
      for (var i = 1, length = arguments.length; i < length; i++) {
        var source = arguments[i];
        for (var prop in source) {
          if (obj[prop] === void 0) obj[prop] = source[prop];
        }
      }
      return obj;
    };
  
    // Create a (shallow-cloned) duplicate of an object.
    _.clone = function(obj) {
      if (!_.isObject(obj)) return obj;
      return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
    };
  
    // Invokes interceptor with the obj, and then returns obj.
    // The primary purpose of this method is to "tap into" a method chain, in
    // order to perform operations on intermediate results within the chain.
    _.tap = function(obj, interceptor) {
      interceptor(obj);
      return obj;
    };
  
    // Internal recursive comparison function for `isEqual`.
    var eq = function(a, b, aStack, bStack) {
      // Identical objects are equal. `0 === -0`, but they aren't identical.
      // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
      if (a === b) return a !== 0 || 1 / a === 1 / b;
      // A strict comparison is necessary because `null == undefined`.
      if (a == null || b == null) return a === b;
      // Unwrap any wrapped objects.
      if (a instanceof _) a = a._wrapped;
      if (b instanceof _) b = b._wrapped;
      // Compare `[[Class]]` names.
      var className = toString.call(a);
      if (className !== toString.call(b)) return false;
      switch (className) {
        // Strings, numbers, regular expressions, dates, and booleans are compared by value.
        case '[object RegExp]':
        // RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i')
        case '[object String]':
          // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
          // equivalent to `new String("5")`.
          return '' + a === '' + b;
        case '[object Number]':
          // `NaN`s are equivalent, but non-reflexive.
          // Object(NaN) is equivalent to NaN
          if (+a !== +a) return +b !== +b;
          // An `egal` comparison is performed for other numeric values.
          return +a === 0 ? 1 / +a === 1 / b : +a === +b;
        case '[object Date]':
        case '[object Boolean]':
          // Coerce dates and booleans to numeric primitive values. Dates are compared by their
          // millisecond representations. Note that invalid dates with millisecond representations
          // of `NaN` are not equivalent.
          return +a === +b;
      }
      if (typeof a != 'object' || typeof b != 'object') return false;
      // Assume equality for cyclic structures. The algorithm for detecting cyclic
      // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
      var length = aStack.length;
      while (length--) {
        // Linear search. Performance is inversely proportional to the number of
        // unique nested structures.
        if (aStack[length] === a) return bStack[length] === b;
      }
      // Objects with different constructors are not equivalent, but `Object`s
      // from different frames are.
      var aCtor = a.constructor, bCtor = b.constructor;
      if (
        aCtor !== bCtor &&
        // Handle Object.create(x) cases
        'constructor' in a && 'constructor' in b &&
        !(_.isFunction(aCtor) && aCtor instanceof aCtor &&
          _.isFunction(bCtor) && bCtor instanceof bCtor)
      ) {
        return false;
      }
      // Add the first object to the stack of traversed objects.
      aStack.push(a);
      bStack.push(b);
      var size, result;
      // Recursively compare objects and arrays.
      if (className === '[object Array]') {
        // Compare array lengths to determine if a deep comparison is necessary.
        size = a.length;
        result = size === b.length;
        if (result) {
          // Deep compare the contents, ignoring non-numeric properties.
          while (size--) {
            if (!(result = eq(a[size], b[size], aStack, bStack))) break;
          }
        }
      } else {
        // Deep compare objects.
        var keys = _.keys(a), key;
        size = keys.length;
        // Ensure that both objects contain the same number of properties before comparing deep equality.
        result = _.keys(b).length === size;
        if (result) {
          while (size--) {
            // Deep compare each member
            key = keys[size];
            if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break;
          }
        }
      }
      // Remove the first object from the stack of traversed objects.
      aStack.pop();
      bStack.pop();
      return result;
    };
  
    // Perform a deep comparison to check if two objects are equal.
    _.isEqual = function(a, b) {
      return eq(a, b, [], []);
    };
  
    // Is a given array, string, or object empty?
    // An "empty" object has no enumerable own-properties.
    _.isEmpty = function(obj) {
      if (obj == null) return true;
      if (_.isArray(obj) || _.isString(obj) || _.isArguments(obj)) return obj.length === 0;
      for (var key in obj) if (_.has(obj, key)) return false;
      return true;
    };
  
    // Is a given value a DOM element?
    _.isElement = function(obj) {
      return !!(obj && obj.nodeType === 1);
    };
  
    // Is a given value an array?
    // Delegates to ECMA5's native Array.isArray
    _.isArray = nativeIsArray || function(obj) {
      return toString.call(obj) === '[object Array]';
    };
  
    // Is a given variable an object?
    _.isObject = function(obj) {
      var type = typeof obj;
      return type === 'function' || type === 'object' && !!obj;
    };
  
    // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp.
    _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) {
      _['is' + name] = function(obj) {
        return toString.call(obj) === '[object ' + name + ']';
      };
    });
  
    // Define a fallback version of the method in browsers (ahem, IE), where
    // there isn't any inspectable "Arguments" type.
    if (!_.isArguments(arguments)) {
      _.isArguments = function(obj) {
        return _.has(obj, 'callee');
      };
    }
  
    // Optimize `isFunction` if appropriate. Work around an IE 11 bug.
    if (typeof /./ !== 'function') {
      _.isFunction = function(obj) {
        return typeof obj == 'function' || false;
      };
    }
  
    // Is a given object a finite number?
    _.isFinite = function(obj) {
      return isFinite(obj) && !isNaN(parseFloat(obj));
    };
  
    // Is the given value `NaN`? (NaN is the only number which does not equal itself).
    _.isNaN = function(obj) {
      return _.isNumber(obj) && obj !== +obj;
    };
  
    // Is a given value a boolean?
    _.isBoolean = function(obj) {
      return obj === true || obj === false || toString.call(obj) === '[object Boolean]';
    };
  
    // Is a given value equal to null?
    _.isNull = function(obj) {
      return obj === null;
    };
  
    // Is a given variable undefined?
    _.isUndefined = function(obj) {
      return obj === void 0;
    };
  
    // Shortcut function for checking if an object has a given property directly
    // on itself (in other words, not on a prototype).
    _.has = function(obj, key) {
      return obj != null && hasOwnProperty.call(obj, key);
    };
  
    // Utility Functions
    // -----------------
  
    // Run Underscore.js in *noConflict* mode, returning the `_` variable to its
    // previous owner. Returns a reference to the Underscore object.
    _.noConflict = function() {
      root._ = previousUnderscore;
      return this;
    };
  
    // Keep the identity function around for default iteratees.
    _.identity = function(value) {
      return value;
    };
  
    _.constant = function(value) {
      return function() {
        return value;
      };
    };
  
    _.noop = function(){};
  
    _.property = function(key) {
      return function(obj) {
        return obj[key];
      };
    };
  
    // Returns a predicate for checking whether an object has a given set of `key:value` pairs.
    _.matches = function(attrs) {
      var pairs = _.pairs(attrs), length = pairs.length;
      return function(obj) {
        if (obj == null) return !length;
        obj = new Object(obj);
        for (var i = 0; i < length; i++) {
          var pair = pairs[i], key = pair[0];
          if (pair[1] !== obj[key] || !(key in obj)) return false;
        }
        return true;
      };
    };
  
    // Run a function **n** times.
    _.times = function(n, iteratee, context) {
      var accum = Array(Math.max(0, n));
      iteratee = createCallback(iteratee, context, 1);
      for (var i = 0; i < n; i++) accum[i] = iteratee(i);
      return accum;
    };
  
    // Return a random integer between min and max (inclusive).
    _.random = function(min, max) {
      if (max == null) {
        max = min;
        min = 0;
      }
      return min + Math.floor(Math.random() * (max - min + 1));
    };
  
    // A (possibly faster) way to get the current timestamp as an integer.
    _.now = Date.now || function() {
      return new Date().getTime();
    };
  
     // List of HTML entities for escaping.
    var escapeMap = {
      '&': '&amp;',
      '<': '&lt;',
      '>': '&gt;',
      '"': '&quot;',
      "'": '&#x27;',
      '`': '&#x60;'
    };
    var unescapeMap = _.invert(escapeMap);
  
    // Functions for escaping and unescaping strings to/from HTML interpolation.
    var createEscaper = function(map) {
      var escaper = function(match) {
        return map[match];
      };
      // Regexes for identifying a key that needs to be escaped
      var source = '(?:' + _.keys(map).join('|') + ')';
      var testRegexp = RegExp(source);
      var replaceRegexp = RegExp(source, 'g');
      return function(string) {
        string = string == null ? '' : '' + string;
        return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
      };
    };
    _.escape = createEscaper(escapeMap);
    _.unescape = createEscaper(unescapeMap);
  
    // If the value of the named `property` is a function then invoke it with the
    // `object` as context; otherwise, return it.
    _.result = function(object, property) {
      if (object == null) return void 0;
      var value = object[property];
      return _.isFunction(value) ? object[property]() : value;
    };
  
    // Generate a unique integer id (unique within the entire client session).
    // Useful for temporary DOM ids.
    var idCounter = 0;
    _.uniqueId = function(prefix) {
      var id = ++idCounter + '';
      return prefix ? prefix + id : id;
    };
  
    // By default, Underscore uses ERB-style template delimiters, change the
    // following template settings to use alternative delimiters.
    _.templateSettings = {
      evaluate    : /<%([\s\S]+?)%>/g,
      interpolate : /<%=([\s\S]+?)%>/g,
      escape      : /<%-([\s\S]+?)%>/g
    };
  
    // When customizing `templateSettings`, if you don't want to define an
    // interpolation, evaluation or escaping regex, we need one that is
    // guaranteed not to match.
    var noMatch = /(.)^/;
  
    // Certain characters need to be escaped so that they can be put into a
    // string literal.
    var escapes = {
      "'":      "'",
      '\\':     '\\',
      '\r':     'r',
      '\n':     'n',
      '\u2028': 'u2028',
      '\u2029': 'u2029'
    };
  
    var escaper = /\\|'|\r|\n|\u2028|\u2029/g;
  
    var escapeChar = function(match) {
      return '\\' + escapes[match];
    };
  
    // JavaScript micro-templating, similar to John Resig's implementation.
    // Underscore templating handles arbitrary delimiters, preserves whitespace,
    // and correctly escapes quotes within interpolated code.
    // NB: `oldSettings` only exists for backwards compatibility.
    _.template = function(text, settings, oldSettings) {
      if (!settings && oldSettings) settings = oldSettings;
      settings = _.defaults({}, settings, _.templateSettings);
  
      // Combine delimiters into one regular expression via alternation.
      var matcher = RegExp([
        (settings.escape || noMatch).source,
        (settings.interpolate || noMatch).source,
        (settings.evaluate || noMatch).source
      ].join('|') + '|$', 'g');
  
      // Compile the template source, escaping string literals appropriately.
      var index = 0;
      var source = "__p+='";
      text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
        source += text.slice(index, offset).replace(escaper, escapeChar);
        index = offset + match.length;
  
        if (escape) {
          source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
        } else if (interpolate) {
          source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
        } else if (evaluate) {
          source += "';\n" + evaluate + "\n__p+='";
        }
  
        // Adobe VMs need the match returned to produce the correct offest.
        return match;
      });
      source += "';\n";
  
      // If a variable is not specified, place data values in local scope.
      if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
  
      source = "var __t,__p='',__j=Array.prototype.join," +
        "print=function(){__p+=__j.call(arguments,'');};\n" +
        source + 'return __p;\n';
  
      try {
        var render = new Function(settings.variable || 'obj', '_', source);
      } catch (e) {
        e.source = source;
        throw e;
      }
  
      var template = function(data) {
        return render.call(this, data, _);
      };
  
      // Provide the compiled source as a convenience for precompilation.
      var argument = settings.variable || 'obj';
      template.source = 'function(' + argument + '){\n' + source + '}';
  
      return template;
    };
  
    // Add a "chain" function. Start chaining a wrapped Underscore object.
    _.chain = function(obj) {
      var instance = _(obj);
      instance._chain = true;
      return instance;
    };
  
    // OOP
    // ---------------
    // If Underscore is called as a function, it returns a wrapped object that
    // can be used OO-style. This wrapper holds altered versions of all the
    // underscore functions. Wrapped objects may be chained.
  
    // Helper function to continue chaining intermediate results.
    var result = function(obj) {
      return this._chain ? _(obj).chain() : obj;
    };
  
    // Add your own custom functions to the Underscore object.
    _.mixin = function(obj) {
      _.each(_.functions(obj), function(name) {
        var func = _[name] = obj[name];
        _.prototype[name] = function() {
          var args = [this._wrapped];
          push.apply(args, arguments);
          return result.call(this, func.apply(_, args));
        };
      });
    };
  
    // Add all of the Underscore functions to the wrapper object.
    _.mixin(_);
  
    // Add all mutator Array functions to the wrapper.
    _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
      var method = ArrayProto[name];
      _.prototype[name] = function() {
        var obj = this._wrapped;
        method.apply(obj, arguments);
        if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0];
        return result.call(this, obj);
      };
    });
  
    // Add all accessor Array functions to the wrapper.
    _.each(['concat', 'join', 'slice'], function(name) {
      var method = ArrayProto[name];
      _.prototype[name] = function() {
        return result.call(this, method.apply(this._wrapped, arguments));
      };
    });
  
    // Extracts the result from a wrapped and chained object.
    _.prototype.value = function() {
      return this._wrapped;
    };
  
    // AMD registration happens at the end for compatibility with AMD loaders
    // that may not enforce next-turn semantics on modules. Even though general
    // practice for AMD registration is to be anonymous, underscore registers
    // as a named module because, like jQuery, it is a base library that is
    // popular enough to be bundled in a third party lib, but not be part of
    // an AMD load request. Those cases could generate an error when an
    // anonymous define() is called outside of a loader request.
    if (typeof define === 'function' && define.amd) {
      define('underscore', [], function() {
        return _;
      });
    }
  }.call(this));
  
  },{}]},{},[2]);
  