https://github.com/jampekka/webtrajsim
Raw File
Tip revision: 61b0c3047004e8dfa7ee181975b13b94a3cf9668 authored by Jami Pekkanen on 28 December 2016, 19:53:27 UTC
Texture filtering tweaking
Tip revision: 61b0c30
ui-main.ls.js
!function(e){function r(e,r,o){return 4===arguments.length?t.apply(this,arguments):void n(e,{declarative:!0,deps:r,declare:o})}function t(e,r,t,o){n(e,{declarative:!1,deps:r,executingRequire:t,execute:o})}function n(e,r){r.name=e,e in v||(v[e]=r),r.normalizedDeps=r.deps}function o(e,r){if(r[e.groupIndex]=r[e.groupIndex]||[],-1==g.call(r[e.groupIndex],e)){r[e.groupIndex].push(e);for(var t=0,n=e.normalizedDeps.length;n>t;t++){var a=e.normalizedDeps[t],u=v[a];if(u&&!u.evaluated){var d=e.groupIndex+(u.declarative!=e.declarative);if(void 0===u.groupIndex||u.groupIndex<d){if(void 0!==u.groupIndex&&(r[u.groupIndex].splice(g.call(r[u.groupIndex],u),1),0==r[u.groupIndex].length))throw new TypeError("Mixed dependency cycle detected");u.groupIndex=d}o(u,r)}}}}function a(e){var r=v[e];r.groupIndex=0;var t=[];o(r,t);for(var n=!!r.declarative==t.length%2,a=t.length-1;a>=0;a--){for(var u=t[a],i=0;i<u.length;i++){var s=u[i];n?d(s):l(s)}n=!n}}function u(e){return y[e]||(y[e]={name:e,dependencies:[],exports:{},importers:[]})}function d(r){if(!r.module){var t=r.module=u(r.name),n=r.module.exports,o=r.declare.call(e,function(e,r){if(t.locked=!0,"object"==typeof e)for(var o in e)n[o]=e[o];else n[e]=r;for(var a=0,u=t.importers.length;u>a;a++){var d=t.importers[a];if(!d.locked)for(var i=0;i<d.dependencies.length;++i)d.dependencies[i]===t&&d.setters[i](n)}return t.locked=!1,r},r.name);t.setters=o.setters,t.execute=o.execute;for(var a=0,i=r.normalizedDeps.length;i>a;a++){var l,s=r.normalizedDeps[a],c=v[s],f=y[s];f?l=f.exports:c&&!c.declarative?l=c.esModule:c?(d(c),f=c.module,l=f.exports):l=p(s),f&&f.importers?(f.importers.push(t),t.dependencies.push(f)):t.dependencies.push(null),t.setters[a]&&t.setters[a](l)}}}function i(e){var r,t=v[e];if(t)t.declarative?f(e,[]):t.evaluated||l(t),r=t.module.exports;else if(r=p(e),!r)throw new Error("Unable to load dependency "+e+".");return(!t||t.declarative)&&r&&r.__useDefault?r["default"]:r}function l(r){if(!r.module){var t={},n=r.module={exports:t,id:r.name};if(!r.executingRequire)for(var o=0,a=r.normalizedDeps.length;a>o;o++){var u=r.normalizedDeps[o],d=v[u];d&&l(d)}r.evaluated=!0;var c=r.execute.call(e,function(e){for(var t=0,n=r.deps.length;n>t;t++)if(r.deps[t]==e)return i(r.normalizedDeps[t]);throw new TypeError("Module "+e+" not declared as a dependency.")},t,n);c&&(n.exports=c),t=n.exports,t&&t.__esModule?r.esModule=t:r.esModule=s(t)}}function s(r){var t={};if(("object"==typeof r||"function"==typeof r)&&r!==e)if(m)for(var n in r)"default"!==n&&c(t,r,n);else{var o=r&&r.hasOwnProperty;for(var n in r)"default"===n||o&&!r.hasOwnProperty(n)||(t[n]=r[n])}return t["default"]=r,x(t,"__useDefault",{value:!0}),t}function c(e,r,t){try{var n;(n=Object.getOwnPropertyDescriptor(r,t))&&x(e,t,n)}catch(o){return e[t]=r[t],!1}}function f(r,t){var n=v[r];if(n&&!n.evaluated&&n.declarative){t.push(r);for(var o=0,a=n.normalizedDeps.length;a>o;o++){var u=n.normalizedDeps[o];-1==g.call(t,u)&&(v[u]?f(u,t):p(u))}n.evaluated||(n.evaluated=!0,n.module.execute.call(e))}}function p(e){if(I[e])return I[e];if("@node/"==e.substr(0,6))return D(e.substr(6));var r=v[e];if(!r)throw"Module "+e+" not present.";return a(e),f(e,[]),v[e]=void 0,r.declarative&&x(r.module.exports,"__esModule",{value:!0}),I[e]=r.declarative?r.module.exports:r.esModule}var v={},g=Array.prototype.indexOf||function(e){for(var r=0,t=this.length;t>r;r++)if(this[r]===e)return r;return-1},m=!0;try{Object.getOwnPropertyDescriptor({a:0},"a")}catch(h){m=!1}var x;!function(){try{Object.defineProperty({},"a",{})&&(x=Object.defineProperty)}catch(e){x=function(e,r,t){try{e[r]=t.value||t.get.call(e)}catch(n){}}}}();var y={},D="undefined"!=typeof System&&System._nodeRequire||"undefined"!=typeof require&&require.resolve&&"undefined"!=typeof process&&require,I={"@empty":{}};return function(e,n,o,a){return function(u){u(function(u){for(var d={_nodeRequire:D,register:r,registerDynamic:t,get:p,set:function(e,r){I[e]=r},newModule:function(e){return e}},i=0;i<n.length;i++)(function(e,r){r&&r.__esModule?I[e]=r:I[e]=s(r)})(n[i],arguments[i]);a(d);var l=p(e[0]);if(e.length>1)for(var i=1;i<e.length;i++)p(e[i]);return o?l["default"]:l})}}}("undefined"!=typeof self?self:global)

(["1"], [], true, function($__System) {
var require = this.require, exports = this.exports, module = this.module;
!function(e){function r(e,r){for(var n=e.split(".");n.length;)r=r[n.shift()];return r}function n(n){if("string"==typeof n)return r(n,e);if(!(n instanceof Array))throw new Error("Global exports must be a string or array.");for(var t={},o=!0,f=0;f<n.length;f++){var i=r(n[f],e);o&&(t["default"]=i,o=!1),t[n[f].split(".").pop()]=i}return t}function t(r){if(Object.keys)Object.keys(e).forEach(r);else for(var n in e)a.call(e,n)&&r(n)}function o(r){t(function(n){if(-1==l.call(s,n)){try{var t=e[n]}catch(o){s.push(n)}r(n,t)}})}var f,i=$__System,a=Object.prototype.hasOwnProperty,l=Array.prototype.indexOf||function(e){for(var r=0,n=this.length;n>r;r++)if(this[r]===e)return r;return-1},s=["_g","sessionStorage","localStorage","clipboardData","frames","frameElement","external","mozAnimationStartTime","webkitStorageInfo","webkitIndexedDB","mozInnerScreenY","mozInnerScreenX"];i.set("@@global-helpers",i.newModule({prepareGlobal:function(r,t,i){var a=e.define;e.define=void 0;var l;if(i){l={};for(var s in i)l[s]=e[s],e[s]=i[s]}return t||(f={},o(function(e,r){f[e]=r})),function(){var r;if(t)r=n(t);else{r={};var i,s;o(function(e,n){f[e]!==n&&"undefined"!=typeof n&&(r[e]=n,"undefined"!=typeof i?s||i===n||(s=!0):i=n)}),r=s?r:i}if(l)for(var u in l)e[u]=l[u];return e.define=a,r}}}))}("undefined"!=typeof self?self:global);
!function(e){function n(e,n){e=e.replace(l,"");var r=e.match(u),t=(r[1].split(",")[n]||"require").replace(s,""),i=p[t]||(p[t]=new RegExp(a+t+f,"g"));i.lastIndex=0;for(var o,c=[];o=i.exec(e);)c.push(o[2]||o[3]);return c}function r(e,n,t,o){if("object"==typeof e&&!(e instanceof Array))return r.apply(null,Array.prototype.splice.call(arguments,1,arguments.length-1));if("string"==typeof e&&"function"==typeof n&&(e=[e]),!(e instanceof Array)){if("string"==typeof e){var l=i.get(e);return l.__useDefault?l["default"]:l}throw new TypeError("Invalid require")}for(var a=[],f=0;f<e.length;f++)a.push(i["import"](e[f],o));Promise.all(a).then(function(e){n&&n.apply(null,e)},t)}function t(t,l,a){"string"!=typeof t&&(a=l,l=t,t=null),l instanceof Array||(a=l,l=["require","exports","module"].splice(0,a.length)),"function"!=typeof a&&(a=function(e){return function(){return e}}(a)),void 0===l[l.length-1]&&l.pop();var f,u,s;-1!=(f=o.call(l,"require"))&&(l.splice(f,1),t||(l=l.concat(n(a.toString(),f)))),-1!=(u=o.call(l,"exports"))&&l.splice(u,1),-1!=(s=o.call(l,"module"))&&l.splice(s,1);var p={name:t,deps:l,execute:function(n,t,o){for(var p=[],c=0;c<l.length;c++)p.push(n(l[c]));o.uri=o.id,o.config=function(){},-1!=s&&p.splice(s,0,o),-1!=u&&p.splice(u,0,t),-1!=f&&p.splice(f,0,function(e,t,l){return"string"==typeof e&&"function"!=typeof t?n(e):r.call(i,e,t,l,o.id)});var d=a.apply(-1==u?e:t,p);return"undefined"==typeof d&&o&&(d=o.exports),"undefined"!=typeof d?d:void 0}};if(t)c.anonDefine||c.isBundle?c.anonDefine&&c.anonDefine.name&&(c.anonDefine=null):c.anonDefine=p,c.isBundle=!0,i.registerDynamic(p.name,p.deps,!1,p.execute);else{if(c.anonDefine&&!c.anonDefine.name)throw new Error("Multiple anonymous defines in module "+t);c.anonDefine=p}}var i=$__System,o=Array.prototype.indexOf||function(e){for(var n=0,r=this.length;r>n;n++)if(this[n]===e)return n;return-1},l=/(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/gm,a="(?:^|[^$_a-zA-Z\\xA0-\\uFFFF.])",f="\\s*\\(\\s*(\"([^\"]+)\"|'([^']+)')\\s*\\)",u=/\(([^\)]*)\)/,s=/^\s+|\s+$/g,p={};t.amd={};var c={isBundle:!1,anonDefine:null};i.amdDefine=t,i.amdRequire=r}("undefined"!=typeof self?self:global);
$__System.registerDynamic("2", [], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  var string,
      TABS,
      unlines,
      enlines,
      enslash,
      reslash,
      camelize,
      deheregex,
      character,
      KEYWORDS_SHARED,
      KEYWORDS_UNUSED,
      JS_KEYWORDS,
      LS_KEYWORDS,
      ID,
      SYMBOL,
      SPACE,
      MULTIDENT,
      SIMPLESTR,
      JSTOKEN,
      BSTOKEN,
      NUMBER,
      NUMBER_OMIT,
      REGEX,
      HEREGEX_OMIT,
      LASTDENT,
      INLINEDENT,
      NONASCII,
      OPENERS,
      CLOSERS,
      INVERSES,
      i,
      o,
      c,
      CHAIN,
      ARG,
      BLOCK_USERS,
      this$ = this,
      slice$ = [].slice;
  exports.lex = function(code, options) {
    return clone$(exports).tokenize(code || '', options || {});
  };
  exports.rewrite = function(it) {
    var ref$;
    it || (it = this.tokens);
    firstPass(it);
    addImplicitIndentation(it);
    rewriteBlockless(it);
    addImplicitParentheses(it);
    addImplicitBraces(it);
    expandLiterals(it);
    if (((ref$ = it[0]) != null ? ref$[0] : void 8) === 'NEWLINE') {
      it.shift();
    }
    return it;
  };
  exports.tokenize = function(code, o) {
    var i,
        prevIndex,
        c,
        charsConsumed,
        that;
    this.inter || (code = code.replace(/[\r\u2028\u2029\uFEFF]/g, ''));
    code = '\n' + code;
    this.tokens = [this.last = ['NEWLINE', '\n', 0, 0]];
    this.line = ~-o.line;
    this.column = o.column || 0;
    this.dents = [];
    this.closes = [];
    this.parens = [];
    this.flags = [];
    i = 0;
    prevIndex = i;
    this.charsCounted = 0;
    this.isAtPrefix = true;
    while (c = code.charAt(i)) {
      charsConsumed = i - prevIndex;
      prevIndex = i;
      if (this.charsCounted > charsConsumed) {
        throw new Error('Location information out-of-sync in lexer');
      }
      this.column += charsConsumed - this.charsCounted;
      this.charsCounted = 0;
      switch (c) {
        case ' ':
          i += this.doSpace(code, i);
          break;
        case '\n':
          i += this.doLine(code, i);
          break;
        case '\\':
          i += this.doBackslash(code, i);
          break;
        case '\'':
        case '"':
          i += this.doString(code, i, c);
          break;
        case "0":
        case "1":
        case "2":
        case "3":
        case "4":
        case "5":
        case "6":
        case "7":
        case "8":
        case "9":
          i += this.doNumber(code, i);
          break;
        case '/':
          switch (code.charAt(i + 1)) {
            case '*':
              i += this.doComment(code, i);
              break;
            case '/':
              i += this.doHeregex(code, i);
              break;
            default:
              i += this.doRegex(code, i) || this.doLiteral(code, i);
          }
          break;
        case '`':
          if ('`' === code.charAt(i + 1)) {
            i += this.doJS(code, i);
          } else {
            i += this.doLiteral(code, i);
          }
          break;
        default:
          i += this.doID(code, i) || this.doLiteral(code, i) || this.doSpace(code, i);
      }
    }
    this.dedent(this.dent);
    if (that = this.closes.pop()) {
      this.carp("missing `" + that + "`");
    }
    if (this.inter) {
      this.rest == null && this.carp('unterminated interpolation');
    } else {
      this.last.spaced = true;
      this.newline();
    }
    o.raw || this.rewrite();
    return this.tokens;
  };
  exports.dent = 0;
  exports.identifiers = {};
  exports.hasOwn = Object.prototype.hasOwnProperty;
  exports.checkConsistency = function(camel, id) {
    if (this.hasOwn.call(this.identifiers, camel) && this.identifiers[camel] !== id) {
      throw new ReferenceError("Inconsistent use of " + camel + " as " + id + " on line " + (-~this.line));
    } else {
      return this.identifiers[camel] = id;
    }
  };
  exports.doID = function(code, index) {
    var regexMatch,
        input,
        id,
        e,
        last,
        ref$,
        tag,
        ref1$,
        that;
    input = (regexMatch = (ID.lastIndex = index, ID).exec(code))[0];
    if (!input) {
      return 0;
    }
    id = camelize(regexMatch[1]);
    if (/-/.test(regexMatch[1])) {
      this.checkConsistency(id, regexMatch[1]);
    }
    if (NONASCII.test(id)) {
      try {
        Function("var " + id);
      } catch (e$) {
        e = e$;
        this.carp("invalid identifier '" + id + "'");
      }
    }
    last = this.last;
    if (regexMatch[2] || last[0] === 'DOT' || this.adi()) {
      this.token('ID', in$(id, JS_KEYWORDS) ? (ref$ = Object(id), ref$.reserved = true, ref$) : id);
      if (regexMatch[2]) {
        this.token(':', ':');
      }
      return input.length;
    }
    switch (id) {
      case 'true':
      case 'false':
      case 'on':
      case 'off':
      case 'yes':
      case 'no':
      case 'null':
      case 'void':
      case 'arguments':
      case 'debugger':
        tag = 'LITERAL';
        break;
      case 'new':
      case 'do':
      case 'typeof':
      case 'delete':
        tag = 'UNARY';
        break;
      case 'yield':
        tag = 'YIELD';
        break;
      case 'return':
      case 'throw':
        tag = 'HURL';
        break;
      case 'break':
      case 'continue':
        tag = 'JUMP';
        break;
      case 'this':
      case 'eval':
      case 'super':
        return this.token('LITERAL', id, true).length;
      case 'for':
        id = [];
        this.fset('for', true);
        this.fset('to', false);
        this.fset('by', true);
        break;
      case 'then':
        this.fset('for', false);
        this.fset('to', false);
        break;
      case 'catch':
      case 'function':
        id = '';
        break;
      case 'in':
      case 'of':
        if (this.fget('for')) {
          this.fset('for', false);
          if (id === 'in') {
            this.fset('by', true);
            id = '';
            if (last[0] === 'ID' && ((ref$ = (ref1$ = this.tokens)[ref1$.length - 2][0]) === ',' || ref$ === ']' || ref$ === '}')) {
              id = this.tokens.pop()[1];
              if ((ref$ = this.tokens)[ref$.length - 1][0] === ',') {
                this.tokens.pop();
              }
            }
          }
          break;
        }
      case 'instanceof':
        if (last[1] === '!') {
          id = this.tokens.pop()[1] + id;
        }
        tag = (ref$ = this.tokens)[ref$.length - 1][0] === '(' ? 'BIOPR' : 'RELATION';
        break;
      case 'not':
        if (last.alias && last[1] === '===') {
          return last[1] = '!==', 3;
        }
        tag = 'UNARY';
        id = '!';
        break;
      case 'and':
      case 'or':
      case 'xor':
      case 'is':
      case 'isnt':
        this.unline();
        tag = id === 'is' || id === 'isnt' ? 'COMPARE' : 'LOGIC';
        if (last[0] === '(') {
          tag = 'BIOP';
        }
        this.token(tag, (function() {
          switch (id) {
            case 'is':
              return '===';
            case 'isnt':
              return '!==';
            case 'or':
              return '||';
            case 'and':
              return '&&';
            case 'xor':
              return 'xor';
          }
        }()));
        this.last.alias = true;
        return id.length;
      case 'unless':
        tag = 'IF';
        break;
      case 'until':
        tag = 'WHILE';
        break;
      case 'import':
        if (last[0] === '(') {
          id = '<<<';
          tag = 'BIOP';
        } else {
          if (able(this.tokens)) {
            id = '<<<';
          } else {
            tag = 'DECL';
          }
        }
        break;
      case 'export':
      case 'const':
      case 'var':
        tag = 'DECL';
        break;
      case 'with':
        tag = (function() {
          switch (false) {
            case !able(this.tokens):
              return 'CLONEPORT';
            case last[0] !== '(':
              return 'BIOP';
            default:
              return 'WITH';
          }
        }.call(this));
        break;
      case 'when':
        this.fset('for', false);
        tag = 'CASE';
      case 'case':
        if (this.doCase()) {
          return input.length;
        }
        break;
      case 'match':
        tag = 'SWITCH';
        break;
      case 'loop':
        this.token('WHILE', id);
        this.token('LITERAL', 'true');
        return input.length;
      case 'let':
      case 'own':
        if (last[0] === 'FOR' && !in$(id, last[1])) {
          last[1].push(id);
          return 3;
        }
      default:
        if (in$(id, KEYWORDS_SHARED)) {
          break;
        }
        if (in$(id, KEYWORDS_UNUSED)) {
          this.carp("reserved word '" + id + "'");
        }
        if (!last[1] && ((ref$ = last[0]) === 'FUNCTION' || ref$ === 'GENERATOR' || ref$ === 'LABEL')) {
          last[1] = id;
          last.spaced = false;
          return input.length;
        }
        tag = 'ID';
        switch (id) {
          case 'otherwise':
            if ((ref$ = last[0]) === 'CASE' || ref$ === '|') {
              last[0] = 'DEFAULT';
              return id.length;
            }
            break;
          case 'all':
            if (that = last[1] === '<<<' && '<' || last[1] === 'import' && 'All') {
              last[1] += that;
              return 3;
            }
            break;
          case 'from':
            if (last[1] === 'yield') {
              last[1] += 'from';
              return 4;
            }
            this.forange() && (tag = 'FROM');
            break;
          case 'to':
          case 'til':
            this.forange() && this.tokens.push(['FROM', '', this.line, this.column], ['STRNUM', '0', this.line, this.column]);
            if (this.fget('from')) {
              this.fset('from', false);
              this.fset('by', true);
              tag = 'TO';
            } else if (!last.callable && last[0] === 'STRNUM' && (ref$ = this.tokens)[ref$.length - 2][0] === '[') {
              last[0] = 'RANGE';
              last.op = id;
              return id.length;
            } else if (in$(']', this.closes)) {
              this.token('TO', id);
              return id.length;
            }
            break;
          case 'by':
            if (last[0] === 'STRNUM' && (ref$ = this.tokens)[ref$.length - 2][0] === 'RANGE' && (ref$ = this.tokens)[ref$.length - 3][0] === '[') {
              tag = 'RANGE_BY';
            } else if (in$(']', this.closes)) {
              tag = 'BY';
            } else if (this.fget('by') && last[0] !== 'FOR') {
              tag = 'BY';
              this.fset('by', false);
            }
            break;
          case 'ever':
            if (last[0] === 'FOR') {
              this.fset('for', false);
              last[0] = 'WHILE';
              tag = 'LITERAL';
              id = 'true';
            }
        }
    }
    tag || (tag = regexMatch[1].toUpperCase());
    if ((tag === 'COMPARE' || tag === 'LOGIC' || tag === 'RELATION') && last[0] === '(') {
      tag = tag === 'RELATION' ? 'BIOPR' : 'BIOP';
    }
    if (tag === 'THEN' || tag === 'IF' || tag === 'WHILE') {
      this.fset('for', false);
      this.fset('by', false);
    }
    if (tag === 'RELATION' || tag === 'THEN' || tag === 'ELSE' || tag === 'CASE' || tag === 'DEFAULT' || tag === 'CATCH' || tag === 'FINALLY' || tag === 'IN' || tag === 'OF' || tag === 'FROM' || tag === 'TO' || tag === 'BY' || tag === 'EXTENDS' || tag === 'IMPLEMENTS' || tag === 'WHERE') {
      this.unline();
    }
    this.token(tag, id);
    return input.length;
  };
  exports.doNumber = function(code, lastIndex) {
    var input,
        regexMatch,
        last,
        radix,
        num,
        rnum,
        bound,
        ref$;
    NUMBER.lastIndex = lastIndex;
    if (!(input = (regexMatch = NUMBER.exec(code))[0])) {
      return 0;
    }
    last = this.last;
    if (regexMatch[5] && (last[0] === 'DOT' || this.adi())) {
      this.token('STRNUM', regexMatch[4].replace(NUMBER_OMIT, ''));
      return regexMatch[4].length;
    }
    if (radix = regexMatch[1]) {
      num = parseInt(rnum = regexMatch[2].replace(NUMBER_OMIT, ''), radix);
      bound = false;
      if (radix > 36 || radix < 2) {
        if (/[0-9]/.exec(rnum)) {
          this.carp("invalid number base " + radix + " (with number " + rnum + "),base must be from 2 to 36");
        } else {
          bound = true;
        }
      }
      if (isNaN(num) || num === parseInt(rnum.slice(0, -1), radix)) {
        this.strnum(regexMatch[1]);
        this.token('DOT', '.~');
        this.token('ID', regexMatch[2]);
        return input.length;
      }
      num += '';
    } else {
      num = (regexMatch[3] || input).replace(NUMBER_OMIT, '');
      if (regexMatch[3] && num.charAt() === '0' && ((ref$ = num.charAt(1)) !== '' && ref$ !== '.')) {
        this.carp("deprecated octal literal " + regexMatch[4]);
      }
    }
    if (!last.spaced && last[0] === '+-') {
      last[0] = 'STRNUM';
      last[1] += num;
      return input.length;
    }
    this.strnum(num);
    return input.length;
  };
  exports.doString = function(code, index, q) {
    var parts,
        str;
    if (q === code.charAt(index + 1)) {
      return q === code.charAt(index + 2) ? this.doHeredoc(code, index, q) : (this.strnum(q + q), 2);
    }
    if (q === '"') {
      parts = this.interpolate(code, index, q);
      this.addInterpolated(parts, unlines);
      return parts.size;
    }
    str = (SIMPLESTR.lastIndex = index, SIMPLESTR).exec(code)[0] || this.carp('unterminated string');
    this.strnum(unlines(this.string(q, str.slice(1, -1))));
    return this.countLines(str).length;
  };
  exports.doHeredoc = function(code, index, q) {
    var end,
        raw,
        doc,
        parts,
        tabs,
        i$,
        len$,
        i,
        t;
    if (q === '\'') {
      ~(end = code.indexOf(q + q + q, index + 3)) || this.carp('unterminated heredoc');
      raw = code.slice(index + 3, end);
      doc = raw.replace(LASTDENT, '');
      this.strnum(enlines(this.string(q, lchomp(detab(doc, heretabs(doc))))));
      return this.countLines(raw).length + 6;
    }
    parts = this.interpolate(code, index, q + q + q);
    tabs = heretabs(code.slice(index + 3, index + parts.size - 3).replace(LASTDENT, ''));
    for (i$ = 0, len$ = parts.length; i$ < len$; ++i$) {
      i = i$;
      t = parts[i$];
      if (t[0] === 'S') {
        if (i + 1 === parts.length) {
          t[1] = t[1].replace(LASTDENT, '');
        }
        t[1] = detab(t[1], tabs);
        if (i === 0) {
          t[1] = lchomp(t[1]);
        }
      }
    }
    this.addInterpolated(parts, enlines);
    return parts.size;
  };
  exports.doComment = function(code, index) {
    var comment,
        end,
        ref$;
    comment = ~(end = code.indexOf('*/', index + 2)) ? code.slice(index, end + 2) : code.slice(index) + '*/';
    if ((ref$ = this.last[0]) === 'NEWLINE' || ref$ === 'INDENT' || ref$ === 'THEN') {
      this.token('COMMENT', detab(comment, this.dent));
      this.token('NEWLINE', '\n');
    }
    return this.countLines(comment).length;
  };
  exports.doJS = function(code, lastIndex) {
    var js,
        ref$;
    JSTOKEN.lastIndex = lastIndex;
    js = JSTOKEN.exec(code)[0] || this.carp('unterminated JS literal');
    this.token('LITERAL', (ref$ = Object(detab(js.slice(2, -2), this.dent)), ref$.js = true, ref$), true);
    return this.countLines(js).length;
  };
  exports.doRegex = function(code, index) {
    var divisible,
        ref$,
        input,
        body,
        flag;
    if (divisible = able(this.tokens) || this.last[0] === 'CREMENT') {
      if (!this.last.spaced || ((ref$ = code.charAt(index + 1)) === ' ' || ref$ === '=')) {
        return 0;
      }
    }
    ref$ = (REGEX.lastIndex = index, REGEX).exec(code), input = ref$[0], body = ref$[1], flag = ref$[2];
    if (input) {
      this.regex(body, flag);
    } else if (!divisible && this.last[0] !== '(') {
      this.carp('unterminated regex');
    }
    return input.length;
  };
  exports.doHeregex = function(code, index) {
    var tokens,
        last,
        parts,
        rest,
        flag,
        i$,
        i,
        t,
        dynaflag,
        len$,
        val,
        one;
    tokens = this.tokens, last = this.last;
    parts = this.interpolate(code, index, '//');
    rest = code.slice(index + parts.size);
    flag = this.validate(/^(?:[gimy]{1,4}|[?$]?)/.exec(rest)[0]);
    if (parts[1]) {
      if (flag === '$') {
        this.adi();
        this.token('(', '"');
      } else {
        tokens.push(['ID', 'RegExp', last[2], last[3]], ['CALL(', '', last[2], last[3]]);
        if (flag === '?') {
          for (i$ = parts.length - 1; i$ >= 0; --i$) {
            i = i$;
            t = parts[i$];
            if (t[0] === 'TOKENS') {
              dynaflag = parts.splice(i, 1)[0][1];
              break;
            }
          }
        }
      }
      for (i$ = 0, len$ = parts.length; i$ < len$; ++i$) {
        i = i$;
        t = parts[i$];
        if (t[0] === 'TOKENS') {
          tokens.push.apply(tokens, t[1]);
        } else {
          val = deheregex(t[1]);
          if (one && !val) {
            continue;
          }
          one = tokens.push((t[0] = 'STRNUM', t[1] = this.string('\'', enslash(val)), t));
        }
        tokens.push(['+-', '+', tokens[tokens.length - 1][2], tokens[tokens.length - 1][3]]);
      }
      --tokens.length;
      if (dynaflag || flag >= 'g') {
        this.token(',', ',');
        if (dynaflag) {
          tokens.push.apply(tokens, dynaflag);
        } else {
          this.token('STRNUM', "'" + flag + "'");
        }
      }
      this.token(flag === '$' ? ')' : ')CALL', '');
    } else {
      this.regex(reslash(deheregex(parts[0][1])), flag);
    }
    return parts.size + flag.length;
  };
  exports.doBackslash = function(code, lastIndex) {
    var ref$,
        input,
        word;
    BSTOKEN.lastIndex = lastIndex;
    ref$ = BSTOKEN.exec(code), input = ref$[0], word = ref$[1];
    if (word) {
      this.strnum(this.string('\'', word));
    } else {
      this.countLines(input);
    }
    return input.length;
  };
  exports.doLine = function(code, index) {
    var ref$,
        input,
        tabs,
        length,
        last,
        that,
        delta,
        tag,
        val;
    ref$ = (MULTIDENT.lastIndex = index, MULTIDENT).exec(code), input = ref$[0], tabs = ref$[1];
    length = this.countLines(input).length;
    last = this.last;
    last.eol = true;
    last.spaced = true;
    if (index + length >= code.length) {
      return length;
    }
    if (that = tabs && (this.emender || (this.emender = RegExp('[^' + tabs.charAt() + ']'))).exec(tabs)) {
      this.carp("contaminated indent " + escape(that));
    }
    if (0 > (delta = tabs.length - this.dent)) {
      this.dedent(-delta);
      this.newline();
    } else {
      tag = last[0], val = last[1];
      if (tag === 'ASSIGN' && ((ref$ = val + '') !== '=' && ref$ !== ':=' && ref$ !== '+=') || val === '++' && (ref$ = this.tokens)[ref$.length - 2].spaced || (tag === '+-' || tag === 'PIPE' || tag === 'BACKPIPE' || tag === 'COMPOSE' || tag === 'DOT' || tag === 'LOGIC' || tag === 'MATH' || tag === 'COMPARE' || tag === 'RELATION' || tag === 'SHIFT' || tag === 'IN' || tag === 'OF' || tag === 'TO' || tag === 'BY' || tag === 'FROM' || tag === 'EXTENDS' || tag === 'IMPLEMENTS')) {
        return length;
      }
      if (delta) {
        this.indent(delta);
      } else {
        this.newline();
      }
    }
    this.fset('for', false);
    this.fset('by', false);
    return length;
  };
  exports.doSpace = function(code, lastIndex) {
    var input;
    SPACE.lastIndex = lastIndex;
    if (input = SPACE.exec(code)[0]) {
      this.last.spaced = true;
    }
    return input.length;
  };
  exports.doCase = function() {
    var ref$,
        ref1$;
    this.seenFor = false;
    if (((ref$ = this.last[0]) === 'ASSIGN' || ref$ === '->' || ref$ === ':') || (this.last[0] === 'INDENT' && ((ref$ = (ref1$ = this.tokens)[ref1$.length - 2][0]) === 'ASSIGN' || ref$ === '->' || ref$ === ':'))) {
      this.token('SWITCH', 'switch');
      return this.token('CASE', 'case');
    }
  };
  exports.doLiteral = function(code, index) {
    var sym,
        tag,
        val,
        ref$,
        that;
    if (!(sym = (SYMBOL.lastIndex = index, SYMBOL).exec(code)[0])) {
      return 0;
    }
    switch (tag = val = sym) {
      case '|':
        tag = 'CASE';
        if (this.doCase()) {
          return sym.length;
        }
        break;
      case '|>':
        tag = 'PIPE';
        break;
      case '`':
        tag = 'BACKTICK';
        break;
      case '<<':
      case '>>':
        tag = 'COMPOSE';
        break;
      case '<|':
        tag = 'BACKPIPE';
        break;
      case '+':
      case '-':
        tag = '+-';
        break;
      case '&&':
      case '||':
        tag = 'LOGIC';
        break;
      case '.&.':
      case '.|.':
      case '.^.':
        tag = 'BITWISE';
        break;
      case '^^':
        tag = 'CLONE';
        break;
      case '**':
      case '^':
        tag = 'POWER';
        break;
      case '?':
        if (this.last[0] === '(') {
          this.token('PARAM(', '(');
          this.token(')PARAM', ')');
          this.token('->', '->');
          this.token('ID', 'it');
        } else {
          if (this.last.spaced) {
            tag = 'LOGIC';
          }
        }
        break;
      case '/':
      case '%':
      case '%%':
        tag = 'MATH';
        break;
      case '++':
      case '--':
        tag = 'CREMENT';
        break;
      case '<<<':
      case '<<<<':
        tag = 'IMPORT';
        break;
      case ';':
        tag = 'NEWLINE';
        this.fset('by', false);
        break;
      case '..':
        this.token('LITERAL', '..', true);
        return 2;
      case '.':
        if (this.last[1] === '?') {
          this.last[0] = '?';
        }
        tag = 'DOT';
        break;
      case ',':
        switch (this.last[0]) {
          case ',':
          case '[':
          case '(':
          case 'CALL(':
            this.token('LITERAL', 'void');
            break;
          case 'FOR':
          case 'OWN':
            this.token('ID', '');
        }
        break;
      case '!=':
      case '~=':
        if (!(able(this.tokens) || ((ref$ = this.last[0]) === '(' || ref$ === 'CREMENT'))) {
          this.tokens.push(val === '!=' ? ['UNARY', '!', this.line, this.column] : ['UNARY', '~', this.line, this.column], ['ASSIGN', '=', this.line, this.column]);
          return 2;
        }
      case '!~=':
      case '==':
        val = (function() {
          switch (val) {
            case '~=':
              return '==';
            case '!~=':
              return '!=';
            case '==':
              return '===';
            case '!=':
              return '!==';
          }
        }());
        tag = 'COMPARE';
        break;
      case '===':
      case '!==':
        val += '=';
      case '<':
      case '>':
      case '<=':
      case '>=':
      case '<==':
      case '>==':
      case '>>=':
      case '<<=':
        tag = 'COMPARE';
        break;
      case '.<<.':
      case '.>>.':
      case '.>>>.':
      case '<?':
      case '>?':
        tag = 'SHIFT';
        break;
      case '(':
        if (!(((ref$ = this.last[0]) === 'FUNCTION' || ref$ === 'GENERATOR' || ref$ === 'LET') || this.able(true) || this.last[1] === '.@')) {
          this.token('(', '(');
          this.closes.push(')');
          this.parens.push(this.last);
          return 1;
        }
        tag = 'CALL(';
        this.closes.push(')CALL');
        break;
      case '[':
      case '{':
        this.adi();
        this.closes.push(']}'.charAt(val === '{'));
        break;
      case '}':
        if (this.inter && val !== (ref$ = this.closes)[ref$.length - 1]) {
          this.rest = code.slice(index + 1);
          return 9e9;
        }
      case ']':
      case ')':
        if (tag === ')' && ((ref$ = this.last[0]) === '+-' || ref$ === 'COMPARE' || ref$ === 'LOGIC' || ref$ === 'MATH' || ref$ === 'POWER' || ref$ === 'SHIFT' || ref$ === 'BITWISE' || ref$ === 'CONCAT' || ref$ === 'COMPOSE' || ref$ === 'RELATION' || ref$ === 'PIPE' || ref$ === 'BACKPIPE' || ref$ === 'IMPORT' || ref$ === 'CLONEPORT' || ref$ === 'ASSIGN')) {
          (ref$ = this.tokens)[ref$.length - 1][0] = (function() {
            switch (this.last[0]) {
              case 'RELATION':
                return 'BIOPR';
              case 'PIPE':
                this.parameters(false, -1);
                return 'BIOPP';
              default:
                return 'BIOP';
            }
          }.call(this));
        }
        if (')' === (tag = val = this.pair(val))) {
          this.lpar = this.parens.pop();
        }
        break;
      case '=':
      case ':':
        if (val === ':') {
          switch (this.last[0]) {
            case 'ID':
            case 'STRNUM':
            case ')':
              break;
            case '...':
              this.last[0] = 'STRNUM';
              break;
            default:
              tag = 'LABEL';
              val = '';
          }
          this.token(tag, val);
          return sym.length;
        }
      case ':=':
      case '+=':
      case '-=':
      case '*=':
      case '/=':
      case '%=':
      case '%%=':
      case '<?=':
      case '>?=':
      case '**=':
      case '^=':
      case '.&.=':
      case '.|.=':
      case '.^.=':
      case '.<<.=':
      case '.>>.=':
      case '.>>>.=':
      case '++=':
      case '|>=':
        if (this.last[1] === '.' || this.last[0] === '?' && this.adi()) {
          this.last[1] += val;
          return val.length;
        }
        if (this.last[0] === 'LOGIC') {
          (val = Object(val)).logic = this.tokens.pop()[1];
        } else if ((val === '+=' || val === '-=') && !able(this.tokens) && ((ref$ = this.last[0]) !== '+-' && ref$ !== 'UNARY' && ref$ !== 'LABEL')) {
          this.token('UNARY', val.charAt());
          val = '=';
        }
        tag = 'ASSIGN';
        break;
      case '::=':
        this.token('DOT', '.');
        this.token('ID', 'prototype');
        this.token('IMPORT', '<<');
        return sym.length;
      case '*':
        if (this.last[0] === 'FUNCTION') {
          this.last[0] = 'GENERATOR';
          return sym.length;
        }
        if (that = ((ref$ = this.last[0]) === 'NEWLINE' || ref$ === 'INDENT' || ref$ === 'THEN' || ref$ === '=>') && (INLINEDENT.lastIndex = index + 1, INLINEDENT).exec(code)[0].length) {
          this.tokens.push(['LITERAL', 'void', this.line, this.column], ['ASSIGN', '=', this.line, this.column]);
          this.indent(index + that - 1 - this.dent - code.lastIndexOf('\n', index - 1));
          return that;
        }
        tag = able(this.tokens) || this.last[0] === 'CREMENT' && able(this.tokens, this.tokens.length - 1) || this.last[0] === '(' ? 'MATH' : 'STRNUM';
        break;
      case '@':
        this.adi();
        if (this.last[0] === 'DOT' && this.last[1] === '.' && (ref$ = this.tokens)[ref$.length - 2][0] === 'ID' && (ref$ = this.tokens)[ref$.length - 2][1] === 'constructor') {
          this.tokens.pop();
          this.tokens.pop();
          this.token('LITERAL', 'this', true);
          this.adi();
          this.token('ID', 'constructor', true);
        } else {
          this.token('LITERAL', 'this', true);
        }
        return 1;
      case '@@':
        this.adi();
        this.token('ID', 'constructor', true);
        return 2;
      case '&':
        this.token('LITERAL', 'arguments');
        return 1;
      case '!':
        switch (false) {
          default:
            if (!this.last.spaced) {
              if (this.last[1] === 'require') {
                this.last[0] = 'REQUIRE';
                this.last[1] = 'require!';
              } else if (able(this.tokens, null, true)) {
                this.token('CALL(', '!');
                this.token(')CALL', ')');
              } else if (this.last[1] === 'typeof') {
                this.last[1] = 'classof';
              } else if (this.last[1] === 'delete') {
                this.last[1] = 'jsdelete';
              } else {
                break;
              }
              return 1;
            }
        }
        tag = 'UNARY';
        break;
      case '|':
        tag = 'BITWISE';
        break;
      case '~':
        if (this.dotcat(val)) {
          return 1;
        }
        tag = 'UNARY';
        break;
      case '::':
        this.adi();
        val = 'prototype';
        tag = 'ID';
        break;
      case '=>':
        this.unline();
        this.fset('for', false);
        tag = 'THEN';
        break;
      default:
        if (/^!?(?:--?|~~?)>\*?$/.test(val)) {
          this.parameters(tag = '->');
        } else if (/^\*?<(?:--?|~~?)!?$/.test(val)) {
          this.parameters(tag = '<-');
        } else {
          switch (val.charAt(0)) {
            case '(':
              this.token('CALL(', '(');
              tag = ')CALL';
              val = ')';
              break;
            case '<':
              if (val.length < 4) {
                this.carp('unterminated words');
              }
              this.token('WORDS', val.slice(2, -2), this.adi());
              return this.countLines(val).length;
          }
        }
    }
    if ((tag === '+-' || tag === 'COMPARE' || tag === 'LOGIC' || tag === 'MATH' || tag === 'POWER' || tag === 'SHIFT' || tag === 'BITWISE' || tag === 'CONCAT' || tag === 'RELATION' || tag === 'PIPE' || tag === 'BACKPIPE' || tag === 'COMPOSE' || tag === 'IMPORT') && this.last[0] === '(') {
      tag = tag === 'BACKPIPE' ? 'BIOPBP' : 'BIOP';
    }
    if (tag === ',' || tag === 'CASE' || tag === 'PIPE' || tag === 'BACKPIPE' || tag === 'COMPOSE' || tag === 'DOT' || tag === 'LOGIC' || tag === 'COMPARE' || tag === 'MATH' || tag === 'POWER' || tag === 'IMPORT' || tag === 'SHIFT' || tag === 'BITWISE') {
      this.unline();
    }
    this.token(tag, val);
    return sym.length;
  };
  exports.token = function(tag, value, callable) {
    this.tokens.push(this.last = [tag, value, this.line, this.column]);
    if (callable) {
      this.last.callable = true;
    }
    return value;
  };
  exports.indent = function(delta) {
    this.dent += delta;
    this.dents.push(this.token('INDENT', delta));
    this.closes.push('DEDENT');
  };
  exports.dedent = function(debt) {
    var dent;
    this.dent -= debt;
    while (debt > 0 && (dent = this.dents.pop())) {
      if (debt < dent && !this.inter) {
        this.carp("unmatched dedent (" + debt + " for " + dent + ")");
      }
      this.pair('DEDENT');
      debt -= typeof dent === 'number' ? this.token('DEDENT', dent) : dent;
    }
  };
  exports.newline = function() {
    var ref$;
    this.last[1] === '\n' || this.tokens.push(this.last = (ref$ = ['NEWLINE', '\n', this.line, this.column], ref$.spaced = true, ref$));
  };
  exports.unline = function() {
    var ref$;
    if (!this.tokens[1]) {
      return;
    }
    switch (this.last[0]) {
      case 'INDENT':
        (ref$ = this.dents)[ref$.length - 1] += '';
      case 'NEWLINE':
        this.tokens.length--;
    }
  };
  exports.parameters = function(arrow, offset) {
    var i$,
        ref$,
        i,
        t,
        ref1$;
    if (this.last[0] === ')' && ')' === this.last[1]) {
      this.lpar[0] = 'PARAM(';
      this.last[0] = ')PARAM';
      return;
    }
    if (arrow === '->') {
      this.token('PARAM(', '');
    } else {
      for (i$ = (ref$ = this.tokens).length - 1; i$ >= 0; --i$) {
        i = i$;
        t = ref$[i$];
        if ((ref1$ = t[0]) === 'NEWLINE' || ref1$ === 'INDENT' || ref1$ === 'THEN' || ref1$ === '=>' || ref1$ === '(') {
          break;
        }
      }
      this.tokens.splice(i + 1, 0, ['PARAM(', '', t[2], t[3]]);
    }
    if (offset) {
      this.tokens.splice(this.tokens.length + offset, 0, [')PARAM', '', t[2], t[3]]);
    } else {
      this.token(')PARAM', '');
    }
  };
  exports.interpolate = function(str, idx, end) {
    var parts,
        end0,
        pos,
        i,
        ref$,
        oldLine,
        oldColumn,
        ch,
        c1,
        id,
        stringified,
        length,
        tag,
        e,
        delta,
        nested,
        clone,
        ref1$;
    parts = [];
    end0 = end.charAt(0);
    pos = 0;
    i = -1;
    str = str.slice(idx + end.length);
    ref$ = [this.line, this.column], oldLine = ref$[0], oldColumn = ref$[1];
    this.countLines(end);
    while (ch = str.charAt(++i)) {
      switch (ch) {
        case end0:
          if (end !== str.slice(i, i + end.length)) {
            continue;
          }
          parts.push(['S', this.countLines(str.slice(0, i)), oldLine, oldColumn]);
          this.countLines(end);
          return parts.size = pos + i + end.length * 2, parts;
        case '#':
          c1 = str.charAt(i + 1);
          id = in$(c1, ['@']) && c1 || (ID.lastIndex = i + 1, ID).exec(str)[1];
          if (!(id || c1 === '{')) {
            continue;
          }
          break;
        case '\\':
          ++i;
        default:
          continue;
      }
      if (i || nested && !stringified) {
        stringified = parts.push(['S', this.countLines(str.slice(0, i)), oldLine, oldColumn]);
        ref$ = [this.line, this.column], oldLine = ref$[0], oldColumn = ref$[1];
      }
      if (id) {
        length = id.length;
        if (id === '@') {
          id = 'this';
        }
        if (in$(id, ['this'])) {
          tag = 'LITERAL';
        } else {
          id = camelize(id);
          try {
            Function("'use strict'; var " + id);
          } catch (e$) {
            e = e$;
            this.carp("invalid variable interpolation '" + id + "'");
          }
          tag = 'ID';
        }
        str = str.slice(delta = i + 1 + length);
        parts.push(['TOKENS', nested = [[tag, id, this.line, this.column]]]);
      } else {
        clone = (ref$ = clone$(exports), ref$.inter = true, ref$.emender = this.emender, ref$);
        nested = clone.tokenize(str.slice(i + 2), {
          line: this.line,
          column: this.column + 2,
          raw: true
        });
        delta = str.length - clone.rest.length;
        this.countLines(str.slice(i, delta));
        str = clone.rest;
        while (((ref$ = nested[0]) != null ? ref$[0] : void 8) === 'NEWLINE') {
          nested.shift();
        }
        if (nested.length) {
          nested.unshift(['(', '(', oldLine, oldColumn]);
          nested.push([')', ')', this.line, this.column - 1]);
          parts.push(['TOKENS', nested]);
        }
        ref1$ = [this.line, this.column], oldLine = ref1$[0], oldColumn = ref1$[1];
      }
      pos += delta;
      i = -1;
    }
    this.carp("missing `" + end + "`");
  };
  exports.addInterpolated = function(parts, nlines) {
    var tokens,
        last,
        ref$,
        left,
        right,
        joint,
        callable,
        i$,
        len$,
        i,
        t;
    if (!parts[1]) {
      return this.strnum(nlines(this.string('"', parts[0][1])));
    }
    tokens = this.tokens, last = this.last;
    ref$ = !last.spaced && last[1] === '%' ? (--tokens.length, this.last = last = tokens[tokens.length - 1], ['[', ']', [',', ',']]) : ['(', ')', ['+-', '+']], left = ref$[0], right = ref$[1], joint = ref$[2];
    callable = this.adi();
    tokens.push([left, '"', last[2], last[3]]);
    for (i$ = 0, len$ = parts.length; i$ < len$; ++i$) {
      i = i$;
      t = parts[i$];
      if (t[0] === 'TOKENS') {
        tokens.push.apply(tokens, t[1]);
      } else {
        if (i > 1 && !t[1]) {
          continue;
        }
        tokens.push(['STRNUM', nlines(this.string('"', t[1])), t[2], t[3]]);
      }
      tokens.push(joint.concat(tokens[tokens.length - 1][2], tokens[tokens.length - 1][3]));
    }
    --tokens.length;
    this.token(right, '', callable);
  };
  exports.strnum = function(it) {
    this.token('STRNUM', it, this.adi() || this.last[0] === 'DOT');
  };
  exports.regex = function(body, flag) {
    var e;
    try {
      RegExp(body);
    } catch (e$) {
      e = e$;
      this.carp(e.message);
    }
    if (flag === '$') {
      return this.strnum(this.string('\'', enslash(body)));
    }
    return this.token('LITERAL', "/" + (body || '(?:)') + "/" + this.validate(flag));
  };
  exports.adi = function() {
    if (this.last.spaced) {
      return;
    }
    if (!able(this.tokens)) {
      return;
    }
    return this.token('DOT', '.');
  };
  exports.dotcat = function(it) {
    if (this.last[1] === '.' || this.adi()) {
      return this.last[1] += it;
    }
  };
  exports.pair = function(it) {
    var wanted,
        ref$;
    if (!(it === (wanted = (ref$ = this.closes)[ref$.length - 1]) || ')CALL' === wanted && it === ')')) {
      if ('DEDENT' !== wanted) {
        this.carp("unmatched `" + it + "`");
      }
      this.dedent((ref$ = this.dents)[ref$.length - 1]);
      return this.pair(it);
    }
    this.unline();
    return this.closes.pop();
  };
  exports.able = function(call) {
    return !this.last.spaced && able(this.tokens, null, call);
  };
  exports.countLines = function(it) {
    var pos;
    if (!this.isAtPrefix) {
      this.column += it.length;
    }
    while (pos = 1 + it.indexOf('\n', pos)) {
      if (!this.isAtPrefix) {
        this.column = 0;
      }
      this.column += it.length - pos;
      ++this.line;
      this.isAtPrefix = false;
    }
    this.charsCounted += it.length;
    return it;
  };
  exports.forange = function() {
    var ref$,
        ref1$,
        ref2$;
    if (((ref$ = (ref1$ = this.tokens)[ref1$.length - 2 - ((ref2$ = this.last[0]) === 'NEWLINE' || ref2$ === 'INDENT')]) != null ? ref$[0] : void 8) === 'FOR' || this.last[0] === 'FOR') {
      this.fset('for', false);
      this.fset('from', true);
      return true;
    } else {
      return false;
    }
  };
  exports.validate = function(flag) {
    var that;
    if (that = flag && /(.).*\1/.exec(flag)) {
      this.carp("duplicate regex flag `" + that[1] + "`");
    }
    return flag;
  };
  exports.fget = function(key) {
    var ref$;
    return (ref$ = this.flags[this.closes.length]) != null ? ref$[key] : void 8;
  };
  exports.fset = function(key, val) {
    var ref$,
        key$;
    ((ref$ = this.flags)[key$ = this.closes.length] || (ref$[key$] = {}))[key] = val;
  };
  exports.carp = function(it) {
    carp(it, this.line);
  };
  exports.string = function(q, body) {
    return string(q, body, this.line);
  };
  function carp(msg, lno) {
    throw SyntaxError(msg + " on line " + (-~lno));
  }
  function able(tokens, i, call) {
    var token,
        tag;
    i == null && (i = tokens.length);
    tag = (token = tokens[i - 1])[0];
    return (tag === 'ID' || tag === ']' || tag === '?') || (call ? token.callable || (tag === ')' || tag === ')CALL' || tag === 'BIOPBP') && token[1] : tag === '}' || tag === ')' || tag === ')CALL' || tag === 'STRNUM' || tag === 'LITERAL' || tag === 'WORDS');
  }
  string = (function(re) {
    return function(q, body, lno) {
      body = body.replace(re, function(it, oct, xu, rest) {
        if (it === q || it === '\\') {
          return '\\' + it;
        }
        if (oct) {
          return '\\x' + (0x100 + parseInt(oct, 8)).toString(16).slice(1);
        }
        if (xu) {
          carp('malformed character escape sequence', lno);
        }
        if (!rest || q === rest) {
          return it;
        } else {
          return rest;
        }
      });
      return q + body + q;
    };
  }.call(this, /['"]|\\(?:([0-3]?[0-7]{2}|[1-7]|0(?=[89]))|x[\dA-Fa-f]{2}|u[\dA-Fa-f]{4}|([xu])|[\\0bfnrtv]|[^\n\S]|([\w\W]))?/g));
  function heretabs(doc) {
    var dent,
        that,
        ref$;
    dent = 0 / 0;
    while (that = TABS.exec(doc)) {
      dent <= (ref$ = that[0].length - 1) || (dent = ref$);
    }
    return dent;
  }
  TABS = /\n(?!$)[^\n\S]*/mg;
  function detab(str, len) {
    if (len) {
      return str.replace(detab[len] || (detab[len] = RegExp('\\n[^\\n\\S]{1,' + len + '}', 'g')), '\n');
    } else {
      return str;
    }
  }
  unlines = function(it) {
    return it.replace(/\n[^\n\S]*/g, '');
  };
  enlines = function(it) {
    return it.replace(/\n/g, '\\n');
  };
  enslash = function(it) {
    return it.replace(/\\/g, '\\\\');
  };
  reslash = function(it) {
    return it.replace(/(\\.)|\//g, function() {
      return arguments[1] || '\\/';
    });
  };
  camelize = function(it) {
    return it.replace(/-[a-z]/ig, function(it) {
      return it.charAt(1).toUpperCase();
    });
  };
  deheregex = function(it) {
    return it.replace(/\s+(?:#.*)?|(\\[\s\S])/g, function(arg$, bs) {
      bs || (bs = '');
      if ('\n' === bs.charAt(1)) {
        return '\\n';
      } else {
        return bs;
      }
    });
  };
  function lchomp(it) {
    return it.slice(1 + it.lastIndexOf('\n', 0));
  }
  function decode(val, lno) {
    if (!isNaN(val)) {
      return [+val];
    }
    val = val.length > 8 ? 'ng' : Function('return ' + val)();
    val.length === 1 || carp('bad string in range', lno);
    return [val.charCodeAt(), true];
  }
  function uxxxx(it) {
    return '"\\u' + ('000' + it.toString(16)).slice(-4) + '"';
  }
  character = typeof JSON == 'undefined' || JSON === null ? uxxxx : function(it) {
    switch (it) {
      case 0x2028:
      case 0x2029:
        return uxxxx(it);
      default:
        return JSON.stringify(String.fromCharCode(it));
    }
  };
  function firstPass(tokens) {
    var prev,
        i,
        token,
        tag,
        val,
        line,
        column,
        next,
        ts,
        parens,
        i$,
        j;
    prev = ['NEWLINE', '\n', 0];
    i = 0;
    while (token = tokens[++i]) {
      tag = token[0], val = token[1], line = token[2], column = token[3];
      switch (false) {
        case !(tag === 'ASSIGN' && in$(prev[1], LS_KEYWORDS) && tokens[i - 2][0] !== 'DOT'):
          carp("cannot assign to reserved word '" + prev[1] + "'", line);
          break;
        case !(tag === 'DOT' && prev[0] === ']' && tokens[i - 2][0] === '[' && tokens[i - 3][0] === 'DOT'):
          tokens.splice(i - 2, 3);
          tokens[i - 3][1] = '[]';
          break;
        case !(tag === 'DOT' && prev[0] === '}' && tokens[i - 2][0] === '{' && tokens[i - 3][0] === 'DOT'):
          tokens.splice(i - 2, 3);
          tokens[i - 3][1] = '{}';
          break;
        case !(val === '.' && token.spaced && prev.spaced):
          tokens[i] = ['COMPOSE', '<<', line, column];
          break;
        case val !== '++':
          if (!(next = tokens[i + 1])) {
            break;
          }
          ts = ['ID', 'LITERAL', 'STRNUM'];
          if (prev.spaced && token.spaced || !(prev.spaced || token.spaced) && in$(prev[0], ts) && in$(next[0], ts)) {
            tokens[i][0] = 'CONCAT';
          }
          if (prev[0] === '(' && next[0] === ')' || prev[0] === '(' && token.spaced || next[0] === ')' && prev.spaced) {
            tokens[i][0] = 'BIOP';
          }
          break;
        case tag !== 'DOT':
          next = tokens[i + 1];
          if (prev[0] === '(' && next[0] === ')') {
            tokens[i][0] = 'BIOP';
          } else if (prev[0] === '(') {
            tokens.splice(i, 0, ['PARAM(', '(', line, column], [')PARAM', ')', line, column], ['->', '~>', line, column], ['ID', 'it', line, column]);
          } else if (next[0] === ')') {
            tokens.splice(i + 1, 0, ['[', '[', line, column], ['ID', 'it', line, column], [']', ']', line, column]);
            parens = 1;
            LOOP: for (i$ = i + 1; i$ >= 0; --i$) {
              j = i$;
              switch (tokens[j][0]) {
                case ')':
                  ++parens;
                  break;
                case '(':
                  if (--parens === 0) {
                    tokens.splice(j + 1, 0, ['PARAM(', '(', line, column], ['ID', 'it', line, column], [')PARAM', ')', line, column], ['->', '~>', line, column]);
                    break LOOP;
                  }
              }
            }
          }
      }
      prev = token;
      continue;
    }
  }
  function rewriteBlockless(tokens) {
    var i,
        token,
        tag;
    i = -1;
    while (token = tokens[++i]) {
      tag = token[0];
      if (tag === 'IF' || tag === 'CLASS' || tag === 'CATCH') {
        detectEnd(tokens, i + 1, ok, go);
      }
    }
    function ok(it) {
      var ref$;
      return (ref$ = it[0]) === 'NEWLINE' || ref$ === 'INDENT';
    }
    function go(it, i) {
      var lno,
          cno;
      if (tag === 'IF') {
        if (it[0] !== 'INDENT' || !it[1] && !it.then || in$(tokens[i - 1][0], BLOCK_USERS)) {
          token[0] = 'POST_IF';
        }
      } else if (it[0] !== 'INDENT') {
        tokens.splice(i, 0, ['INDENT', 0, lno = tokens[i - 1][2], cno = tokens[i - 1][3]], ['DEDENT', 0, lno, cno]);
      }
    }
  }
  function addImplicitIndentation(tokens) {
    var i,
        token,
        tag,
        next,
        indent,
        dedent,
        ref$,
        ref1$,
        idx;
    i = 0;
    while (token = tokens[++i]) {
      tag = token[0];
      if (tag !== '->' && tag !== 'THEN' && tag !== 'ELSE' && tag !== 'DEFAULT' && tag !== 'TRY' && tag !== 'FINALLY' && tag !== 'DECL') {
        continue;
      }
      switch (next = tokens[i + 1][0]) {
        case 'IF':
          if (tag === 'ELSE') {
            continue;
          }
          break;
        case 'INDENT':
        case 'THEN':
          if (tag === 'THEN') {
            tokens.splice(i--, 1);
          }
          continue;
      }
      indent = ['INDENT', 0, token[2], token[3]];
      dedent = ['DEDENT', 0];
      if (tag === 'THEN') {
        (tokens[i] = indent).then = true;
      } else {
        tokens.splice(++i, 0, indent);
      }
      switch (false) {
        case tag !== 'DECL':
          break;
        case next !== 'DOT' && next !== '?' && next !== ',' && next !== 'PIPE' && next !== 'BACKPIPE':
          --i;
        case !((next === 'ID' || next === 'STRNUM' || next === 'LITERAL') && ',' === ((ref$ = tokens[i + 2]) != null ? ref$[0] : void 8)):
          go(0, i += 2);
          ++i;
          continue;
        case !((next === '(' || next === '[' || next === '{') && ',' === ((ref1$ = tokens[idx = 1 + indexOfPair(tokens, i + 1)]) != null ? ref1$[0] : void 8)):
          go(0, idx);
          ++i;
          continue;
      }
      detectEnd(tokens, i + 1, ok, go);
    }
    function ok(token, i) {
      var t0,
          t;
      t0 = token[0];
      t = tag;
      if (tag === t0 || tag === 'THEN' && t0 === 'SWITCH') {
        tag = '';
      }
      switch (t0) {
        case 'NEWLINE':
          return token[1] !== ';';
        case 'DOT':
        case '?':
        case ',':
        case 'PIPE':
        case 'BACKPIPE':
          return tokens[i - 1].eol;
        case 'ELSE':
          return t === 'THEN';
        case 'CATCH':
          return t === 'TRY';
        case 'FINALLY':
          return t === 'TRY' || t === 'CATCH' || t === 'THEN';
        case 'CASE':
        case 'DEFAULT':
          return t === 'CASE' || t === 'THEN';
      }
    }
    function go(arg$, i) {
      var prev;
      prev = tokens[i - 1];
      tokens.splice(prev[0] === ',' ? i - 1 : i, 0, (dedent[2] = prev[2], dedent[3] = prev[3], dedent));
    }
  }
  function addImplicitParentheses(tokens) {
    var i,
        brackets,
        token,
        endi,
        ref$,
        tpair,
        tag,
        prev,
        ref1$,
        skipBlock,
        seenSwitch;
    i = 0;
    brackets = [];
    while (token = tokens[++i]) {
      if (token[1] === 'do' && tokens[i + 1][0] === 'INDENT') {
        endi = indexOfPair(tokens, i + 1);
        if (tokens[endi + 1][0] === 'NEWLINE' && ((ref$ = tokens[endi + 2]) != null ? ref$[0] : void 8) === 'WHILE') {
          token[0] = 'DO';
          tokens[endi + 2].done = true;
          tokens.splice(endi + 1, 1);
        } else {
          (token = tokens[1 + i])[0] = '(';
          (tpair = tokens[endi])[0] = ')';
          token.doblock = true;
          tokens.splice(i, 1);
        }
      }
      tag = token[0];
      prev = tokens[i - 1];
      tag === '[' && brackets.push(prev[0] === 'DOT');
      if (prev[0] === ']') {
        if (brackets.pop()) {
          prev.index = true;
        } else {
          continue;
        }
      }
      if (!(((ref1$ = prev[0]) === 'FUNCTION' || ref1$ === 'GENERATOR' || ref1$ === 'LET' || ref1$ === 'WHERE') || prev.spaced && able(tokens, i, true))) {
        continue;
      }
      if (token.doblock) {
        token[0] = 'CALL(';
        tpair[0] = ')CALL';
        continue;
      }
      if (!exp(token)) {
        continue;
      }
      if (tag === 'CREMENT') {
        if (token.spaced || !in$((ref1$ = tokens[i + 1]) != null ? ref1$[0] : void 8, CHAIN)) {
          continue;
        }
      }
      skipBlock = seenSwitch = false;
      tokens.splice(i++, 0, ['CALL(', '', token[2], token[3]]);
      detectEnd(tokens, i, ok, go);
    }
    function exp(token) {
      var tag;
      tag = token[0];
      return in$(tag, ARG) || !token.spaced && (tag === '+-' || tag === 'CLONE');
    }
    function ok(token, i) {
      var tag,
          ref$,
          pre;
      tag = token[0];
      if (tag === 'POST_IF' || tag === 'PIPE' || tag === 'BACKPIPE') {
        return true;
      }
      if (!skipBlock) {
        if (token.alias && ((ref$ = token[1]) === '&&' || ref$ === '||' || ref$ === 'xor') || (tag === 'TO' || tag === 'BY' || tag === 'IMPLEMENTS')) {
          return true;
        }
      }
      pre = tokens[i - 1];
      switch (tag) {
        case 'NEWLINE':
          return pre[0] !== ',';
        case 'DOT':
        case '?':
          return !skipBlock && (pre.spaced || pre[0] === 'DEDENT');
        case 'SWITCH':
          seenSwitch = true;
        case 'IF':
        case 'CLASS':
        case 'FUNCTION':
        case 'GENERATOR':
        case 'LET':
        case 'WITH':
        case 'CATCH':
          skipBlock = true;
          break;
        case 'CASE':
          if (seenSwitch) {
            skipBlock = true;
          } else {
            return true;
          }
          break;
        case 'INDENT':
          if (skipBlock) {
            return skipBlock = false;
          }
          return !in$(pre[0], BLOCK_USERS);
        case 'WHILE':
          if (token.done) {
            return false;
          }
        case 'FOR':
          skipBlock = true;
          return able(tokens, i) || pre[0] === 'CREMENT' || pre[0] === '...' && pre.spaced;
      }
      return false;
    }
    function go(token, i) {
      tokens.splice(i, 0, [')CALL', '', tokens[i - 1][2], tokens[i - 1][3]]);
    }
  }
  function addImplicitBraces(tokens) {
    var stack,
        i,
        token,
        tag,
        start,
        paren,
        index,
        pre,
        ref$,
        inline,
        ref1$;
    stack = [];
    i = 0;
    while (token = tokens[++i]) {
      if (':' !== (tag = token[0])) {
        switch (false) {
          case !in$(tag, CLOSERS):
            start = stack.pop();
            break;
          case !in$(tag, OPENERS):
            if (tag === 'INDENT' && tokens[i - 1][0] === '{') {
              tag = '{';
            }
            stack.push([tag, i]);
        }
        continue;
      }
      paren = tokens[i - 1][0] === ')';
      index = paren ? start[1] : i - 1;
      pre = tokens[index - 1];
      if (!(((ref$ = pre[0]) === ':' || ref$ === 'ASSIGN' || ref$ === 'IMPORT') || ((ref$ = stack[stack.length - 1]) != null ? ref$[0] : void 8) !== '{')) {
        continue;
      }
      stack.push(['{']);
      inline = !pre.doblock && ((ref1$ = pre[0]) !== 'NEWLINE' && ref1$ !== 'INDENT');
      while (((ref1$ = tokens[index - 2]) != null ? ref1$[0] : void 8) === 'COMMENT') {
        index -= 2;
      }
      tokens.splice(index, 0, ['{', '{', tokens[index][2], tokens[index][3]]);
      detectEnd(tokens, ++i + 1, ok, go);
    }
    function ok(token, i) {
      var tag,
          t1,
          ref$,
          ref1$;
      switch (tag = token[0]) {
        case ',':
          break;
        case 'NEWLINE':
          if (inline) {
            return true;
          }
          break;
        case 'DEDENT':
          return true;
        case 'POST_IF':
        case 'FOR':
        case 'WHILE':
          return inline;
        default:
          return false;
      }
      t1 = (ref$ = tokens[i + 1]) != null ? ref$[0] : void 8;
      return t1 !== (tag === ',' ? 'NEWLINE' : 'COMMENT') && ':' !== ((ref1$ = tokens[t1 === '(' ? 1 + indexOfPair(tokens, i + 1) : i + 2]) != null ? ref1$[0] : void 8);
    }
    function go(token, i) {
      tokens.splice(i, 0, ['}', '', token[2], token[3]]);
    }
  }
  function expandLiterals(tokens) {
    var i,
        fromNum,
        token,
        sig,
        ref$,
        ref1$,
        lno,
        cno,
        ref2$,
        ref3$,
        ref4$,
        char,
        toNum,
        tochar,
        byNum,
        byp,
        ref5$,
        ts,
        enc,
        add,
        i$,
        n,
        ref6$,
        ref7$,
        len$,
        word,
        that;
    i = 0;
    while (token = tokens[++i]) {
      switch (token[0]) {
        case 'STRNUM':
          if (~'-+'.indexOf(sig = token[1].charAt(0))) {
            token[1] = token[1].slice(1);
            tokens.splice(i++, 0, ['+-', sig, token[2], token[3]]);
          }
          if (token.callable) {
            continue;
          }
          break;
        case 'TO':
        case 'TIL':
          if (!(tokens[i - 1][0] === '[' && ((tokens[i + 2][0] === ']' && (((ref$ = tokens[i + 1][1].charAt(0)) === '\'' || ref$ === '"') || +tokens[i + 1][1] >= 0)) || (tokens[i + 2][0] === 'BY' && ((ref$ = tokens[i + 3]) != null ? ref$[0] : void 8) === 'STRNUM' && ((ref1$ = tokens[i + 4]) != null ? ref1$[0] : void 8) === ']')))) {
            continue;
          }
          if (tokens[i + 2][0] === 'BY') {
            tokens[i + 2][0] = 'RANGE_BY';
          }
          token.op = token[1];
          fromNum = 0;
        case 'RANGE':
          lno = token[2];
          cno = token[3];
          if (fromNum != null || (tokens[i - 1][0] === '[' && tokens[i + 1][0] === 'STRNUM' && ((tokens[i + 2][0] === ']' && (((ref2$ = tokens[i + 1][1].charAt(0)) === '\'' || ref2$ === '"') || +tokens[i + 1][1] >= 0)) || (tokens[i + 2][0] === 'RANGE_BY' && ((ref2$ = tokens[i + 3]) != null ? ref2$[0] : void 8) === 'STRNUM' && ((ref3$ = tokens[i + 4]) != null ? ref3$[0] : void 8) === ']')))) {
            if (fromNum == null) {
              ref4$ = decode(token[1], lno), fromNum = ref4$[0], char = ref4$[1];
            }
            ref4$ = decode(tokens[i + 1][1], lno), toNum = ref4$[0], tochar = ref4$[1];
            if (toNum == null || char ^ tochar) {
              carp('bad "to" in range', lno);
            }
            byNum = 1;
            if (byp = ((ref4$ = tokens[i + 2]) != null ? ref4$[0] : void 8) === 'RANGE_BY') {
              if (!(byNum = +((ref5$ = tokens[i + 3]) != null ? ref5$[1] : void 8))) {
                carp('bad "by" in range', tokens[i + 2][2]);
              }
            } else if (fromNum > toNum) {
              byNum = -1;
            }
            ts = [];
            enc = char ? character : String;
            add = fn$;
            if (token.op === 'to') {
              for (i$ = fromNum; byNum < 0 ? i$ >= toNum : i$ <= toNum; i$ += byNum) {
                n = i$;
                add();
              }
            } else {
              for (i$ = fromNum; byNum < 0 ? i$ > toNum : i$ < toNum; i$ += byNum) {
                n = i$;
                add();
              }
            }
            ts.pop() || carp('empty range', lno);
            tokens.splice.apply(tokens, [i, 2 + 2 * byp].concat(slice$.call(ts)));
            i += ts.length - 1;
          } else {
            token[0] = 'STRNUM';
            if (((ref6$ = tokens[i + 2]) != null ? ref6$[0] : void 8) === 'RANGE_BY') {
              tokens.splice(i + 2, 1, ['BY', 'by', lno, cno]);
            }
            tokens.splice(i + 1, 0, ['TO', token.op, lno, cno]);
          }
          fromNum = null;
          break;
        case 'WORDS':
          ts = [['[', '[', lno = token[2], cno = token[3]]];
          for (i$ = 0, len$ = (ref7$ = token[1].match(/\S+/g) || '').length; i$ < len$; ++i$) {
            word = ref7$[i$];
            ts.push(['STRNUM', string('\'', word, lno), lno, cno], [',', ',', lno, cno]);
          }
          tokens.splice.apply(tokens, [i, 1].concat(slice$.call(ts), [[']', ']', lno, cno]]));
          i += ts.length;
          break;
        case 'INDENT':
          if (that = tokens[i - 1]) {
            if (that[1] === 'new') {
              tokens.splice(i++, 0, ['PARAM(', '', token[2], token[3]], [')PARAM', '', token[2], token[3]], ['->', '', token[2], token[3]]);
            } else if ((ref7$ = that[0]) === 'FUNCTION' || ref7$ === 'GENERATOR' || ref7$ === 'LET') {
              tokens.splice(i, 0, ['CALL(', '', token[2], token[3]], [')CALL', '', token[2], token[3]]);
              i += 2;
            }
          }
          continue;
        case 'LITERAL':
        case '}':
          break;
        case ')':
        case ')CALL':
          if (token[1]) {
            continue;
          }
          break;
        case ']':
          if (token.index) {
            continue;
          }
          break;
        case 'CREMENT':
          if (!able(tokens, i)) {
            continue;
          }
          break;
        case 'BIOP':
          if (!token.spaced && ((ref7$ = token[1]) === '+' || ref7$ === '-') && tokens[i + 1][0] !== ')') {
            tokens[i][0] = '+-';
          }
          continue;
        default:
          continue;
      }
      if (token.spaced && in$(tokens[i + 1][0], ARG)) {
        tokens.splice(++i, 0, [',', ',', token[2], token[3]]);
      }
    }
    function fn$() {
      if (0x10000 < ts.push(['STRNUM', enc(n), lno, cno], [',', ',', lno, cno])) {
        carp('range limit exceeded', lno);
      }
    }
  }
  function detectEnd(tokens, i, ok, go) {
    var levels,
        token,
        tag;
    levels = 0;
    for (; token = tokens[i]; ++i) {
      if (!levels && ok(token, i)) {
        return go(token, i);
      }
      tag = token[0];
      if (0 > (levels += in$(tag, OPENERS) || -in$(tag, CLOSERS))) {
        return go(token, i);
      }
    }
  }
  function indexOfPair(tokens, i) {
    var level,
        end,
        start,
        that;
    level = 1;
    end = INVERSES[start = tokens[i][0]];
    while (that = tokens[++i]) {
      switch (that[0]) {
        case start:
          ++level;
          break;
        case end:
          if (!--level) {
            return i;
          }
      }
    }
    return -1;
  }
  KEYWORDS_SHARED = ['true', 'false', 'null', 'this', 'void', 'super', 'return', 'throw', 'break', 'continue', 'if', 'else', 'for', 'while', 'switch', 'case', 'default', 'try', 'catch', 'finally', 'function', 'class', 'extends', 'implements', 'new', 'do', 'delete', 'typeof', 'in', 'instanceof', 'let', 'with', 'var', 'const', 'import', 'export', 'debugger', 'yield'];
  KEYWORDS_UNUSED = ['enum', 'interface', 'package', 'private', 'protected', 'public', 'static'];
  JS_KEYWORDS = KEYWORDS_SHARED.concat(KEYWORDS_UNUSED);
  LS_KEYWORDS = ['xor', 'match', 'where'];
  ID = /((?!\s)[a-z_$\xAA-\uFFDC](?:(?!\s)[\w$\xAA-\uFFDC]|-[a-z])*)([^\n\S]*:(?![:=]))?|/ig;
  SYMBOL = /[-\/^]=|[%+:*]{1,2}=|\|>=|\.(?:[&\|\^]|<<|>>>?)\.=?|\.{1,3}|\^\^|\*?<(?:--?|~~?)!?|!?(?:--?|~~?)>\*?|([-+&|:])\1|%%|&|\([^\n\S]*\)|[!=]==?|!?\~=|@@?|<\[(?:[\s\S]*?\]>)?|<<<<?|<\||[<>]==|<<=|>>=|<<|>>|[<>]\??=?|\|>|\||=>|\*\*|\^|`|[^\s#]?/g;
  SPACE = /[^\n\S]*(?:#.*)?/g;
  MULTIDENT = /(?:\s*#.*)*(?:\n([^\n\S]*))*/g;
  SIMPLESTR = /'[^\\']*(?:\\[\s\S][^\\']*)*'|/g;
  JSTOKEN = /``[^\\`]*(?:\\[\s\S][^\\`]*)*``|/g;
  BSTOKEN = RegExp('\\\\(?:(\\S[^\\s,;)}\\]]*)|(?:' + SPACE.source + '\\n?)*)', 'g');
  NUMBER = /0x[\dA-Fa-f][\dA-Fa-f_]*|(\d*)~([\dA-Za-z]\w*)|((\d[\d_]*)(\.\d[\d_]*)?(?:e[+-]?\d[\d_]*)?)[$\w]*|/g;
  NUMBER_OMIT = /_+/g;
  REGEX = /\/([^[\/\n\\]*(?:(?:\\.|\[[^\]\n\\]*(?:\\.[^\]\n\\]*)*\])[^[\/\n\\]*)*)\/([gimy]{1,4}|\$?)|/g;
  HEREGEX_OMIT = /\s+(?:#.*)?/g;
  LASTDENT = /\n[^\n\S]*$/;
  INLINEDENT = /[^\n\S]*[^#\s]?/g;
  NONASCII = /[\x80-\uFFFF]/;
  OPENERS = ['(', '[', '{', 'CALL(', 'PARAM(', 'INDENT'];
  CLOSERS = [')', ']', '}', ')CALL', ')PARAM', 'DEDENT'];
  INVERSES = import$((function() {
    var i$,
        ref$,
        len$,
        resultObj$ = {};
    for (i$ = 0, len$ = (ref$ = OPENERS).length; i$ < len$; ++i$) {
      i = i$;
      o = ref$[i$];
      resultObj$[o] = CLOSERS[i];
    }
    return resultObj$;
  }()), (function() {
    var i$,
        ref$,
        len$,
        resultObj$ = {};
    for (i$ = 0, len$ = (ref$ = CLOSERS).length; i$ < len$; ++i$) {
      i = i$;
      c = ref$[i$];
      resultObj$[c] = OPENERS[i];
    }
    return resultObj$;
  }()));
  CHAIN = ['(', '{', '[', 'ID', 'STRNUM', 'LITERAL', 'LET', 'WITH', 'WORDS'];
  ARG = CHAIN.concat(['...', 'UNARY', 'YIELD', 'CREMENT', 'PARAM(', 'FUNCTION', 'GENERATOR', 'IF', 'SWITCH', 'TRY', 'CLASS', 'RANGE', 'LABEL', 'DECL', 'DO', 'BIOPBP']);
  BLOCK_USERS = [',', ':', '->', 'ELSE', 'ASSIGN', 'IMPORT', 'UNARY', 'DEFAULT', 'TRY', 'FINALLY', 'HURL', 'DECL', 'DO', 'LET', 'FUNCTION', 'GENERATOR', '...'];
  function clone$(it) {
    function fun() {}
    fun.prototype = it;
    return new fun;
  }
  function in$(x, xs) {
    var i = -1,
        l = xs.length >>> 0;
    while (++i < l)
      if (x === xs[i])
        return true;
    return false;
  }
  function import$(obj, src) {
    var own = {}.hasOwnProperty;
    for (var key in src)
      if (own.call(src, key))
        obj[key] = src[key];
    return obj;
  }
  return module.exports;
});

$__System.registerDynamic("3", ["4", "5"], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  var parser = (function() {
    var o = function(k, v, o, l) {
      for (o = o || {}, l = k.length; l--; o[k[l]] = v)
        ;
      return o;
    },
        $V0 = [2, 61],
        $V1 = [1, 31],
        $V2 = [1, 34],
        $V3 = [1, 35],
        $V4 = [1, 36],
        $V5 = [1, 37],
        $V6 = [1, 38],
        $V7 = [1, 39],
        $V8 = [1, 8],
        $V9 = [1, 15],
        $Va = [1, 14],
        $Vb = [1, 40],
        $Vc = [1, 41],
        $Vd = [1, 29],
        $Ve = [1, 6],
        $Vf = [1, 10],
        $Vg = [1, 9],
        $Vh = [1, 11],
        $Vi = [1, 16],
        $Vj = [1, 17],
        $Vk = [1, 18],
        $Vl = [1, 19],
        $Vm = [1, 20],
        $Vn = [1, 21],
        $Vo = [1, 23],
        $Vp = [1, 42],
        $Vq = [1, 24],
        $Vr = [1, 25],
        $Vs = [1, 26],
        $Vt = [1, 27],
        $Vu = [1, 28],
        $Vv = [1, 30],
        $Vw = [1, 43],
        $Vx = [1, 22, 27, 46],
        $Vy = [22, 46],
        $Vz = [2, 65],
        $VA = [1, 47],
        $VB = [1, 48],
        $VC = [1, 49],
        $VD = [1, 50],
        $VE = [1, 51],
        $VF = [1, 52],
        $VG = [1, 53],
        $VH = [1, 54],
        $VI = [1, 55],
        $VJ = [1, 56],
        $VK = [1, 57],
        $VL = [1, 58],
        $VM = [1, 59],
        $VN = [1, 60],
        $VO = [1, 61],
        $VP = [32, 45, 46, 47],
        $VQ = [2, 51],
        $VR = [1, 66],
        $VS = [1, 65],
        $VT = [1, 68],
        $VU = [1, 14, 21, 22, 24, 26, 27, 28, 32, 35, 36, 37, 40, 45, 46, 47, 57, 58, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 78, 81, 82, 104],
        $VV = [2, 76],
        $VW = [1, 75],
        $VX = [1, 76],
        $VY = [1, 77],
        $VZ = [1, 72],
        $V_ = [1, 70],
        $V$ = [1, 71],
        $V01 = [1, 73],
        $V11 = [1, 74],
        $V21 = [1, 81],
        $V31 = [1, 85],
        $V41 = [1, 84],
        $V51 = [1, 82],
        $V61 = [1, 93],
        $V71 = [1, 106],
        $V81 = [47, 104],
        $V91 = [2, 209],
        $Va1 = [1, 110],
        $Vb1 = [2, 1],
        $Vc1 = [1, 9, 11, 14, 15, 21, 22, 24, 26, 27, 28, 32, 34, 35, 36, 37, 40, 45, 46, 47, 55, 56, 57, 58, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 78, 81, 82, 96, 102, 103, 104],
        $Vd1 = [21, 45, 46, 47],
        $Ve1 = [24, 45, 46],
        $Vf1 = [2, 164],
        $Vg1 = [1, 132],
        $Vh1 = [1, 133],
        $Vi1 = [1, 130],
        $Vj1 = [1, 131],
        $Vk1 = [1, 134],
        $Vl1 = [1, 122],
        $Vm1 = [1, 126],
        $Vn1 = [1, 127],
        $Vo1 = [1, 125],
        $Vp1 = [27, 46],
        $Vq1 = [1, 148],
        $Vr1 = [1, 149],
        $Vs1 = [32, 46, 47],
        $Vt1 = [2, 59],
        $Vu1 = [1, 171],
        $Vv1 = [14, 21, 22, 32, 45, 46, 47],
        $Vw1 = [2, 56],
        $Vx1 = [2, 72],
        $Vy1 = [14, 45, 46, 47],
        $Vz1 = [1, 14, 21, 22, 24, 26, 27, 28, 32, 36, 37, 40, 45, 46, 47, 57, 58, 61, 62, 63, 65, 66, 67, 69, 70, 71, 78, 81, 82, 104],
        $VA1 = [22, 45, 46, 47],
        $VB1 = [1, 14, 21, 22, 24, 26, 27, 28, 32, 36, 37, 40, 45, 46, 47, 78, 81, 82, 104],
        $VC1 = [2, 173],
        $VD1 = [1, 203],
        $VE1 = [1, 207],
        $VF1 = [1, 14, 21, 22, 24, 26, 27, 28, 32, 35, 36, 37, 40, 45, 46, 47, 57, 58, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 78, 81, 104],
        $VG1 = [1, 210],
        $VH1 = [45, 47, 82],
        $VI1 = [2, 211],
        $VJ1 = [1, 216],
        $VK1 = [1, 14, 21, 22, 24, 26, 27, 28, 32, 36, 37, 40, 45, 46, 47, 70, 71, 78, 81, 82, 104],
        $VL1 = [1, 223],
        $VM1 = [21, 46, 47],
        $VN1 = [24, 46],
        $VO1 = [1, 229],
        $VP1 = [22, 24, 45, 46],
        $VQ1 = [1, 231],
        $VR1 = [22, 24, 45, 46, 56, 62],
        $VS1 = [1, 9, 11, 14, 15, 21, 22, 24, 26, 27, 28, 32, 34, 35, 36, 37, 40, 45, 46, 47, 55, 56, 57, 58, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 78, 81, 82, 96, 100, 102, 103, 104],
        $VT1 = [1, 259],
        $VU1 = [1, 258],
        $VV1 = [21, 22, 24, 40, 46, 47, 81],
        $VW1 = [1, 14, 21, 22, 24, 26, 27, 28, 32, 36, 37, 40, 45, 46, 47, 57, 61, 62, 65, 66, 67, 69, 70, 71, 78, 81, 82, 104],
        $VX1 = [1, 14, 21, 22, 24, 26, 27, 28, 32, 36, 37, 40, 45, 46, 47, 62, 66, 70, 71, 78, 81, 82, 104],
        $VY1 = [1, 14, 21, 22, 24, 26, 27, 28, 32, 36, 37, 40, 45, 46, 47, 61, 62, 66, 69, 70, 71, 78, 81, 82, 104],
        $VZ1 = [1, 270],
        $V_1 = [1, 271],
        $V$1 = [2, 60],
        $V02 = [14, 46, 47],
        $V12 = [22, 46, 47],
        $V22 = [1, 308],
        $V32 = [1, 309],
        $V42 = [1, 318],
        $V52 = [1, 348],
        $V62 = [1, 349],
        $V72 = [1, 14, 21, 22, 24, 26, 27, 28, 32, 35, 36, 37, 40, 45, 46, 47, 57, 58, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 78, 81, 82, 88, 89, 104],
        $V82 = [1, 423];
    var parser = {
      trace: function trace() {},
      yy: {},
      symbols_: {
        "error": 2,
        "Chain": 3,
        "ID": 4,
        "Parenthetical": 5,
        "List": 6,
        "STRNUM": 7,
        "LITERAL": 8,
        "DOT": 9,
        "Key": 10,
        "CALL(": 11,
        "ArgList": 12,
        "OptComma": 13,
        ")CALL": 14,
        "?": 15,
        "LET": 16,
        "Block": 17,
        "[": 18,
        "Expression": 19,
        "LoopHeads": 20,
        "]": 21,
        "DEDENT": 22,
        "{": 23,
        "}": 24,
        "(": 25,
        "BIOP": 26,
        ")": 27,
        "BIOPR": 28,
        "BIOPBP": 29,
        "BIOPP": 30,
        "PARAM(": 31,
        ")PARAM": 32,
        "UNARY": 33,
        "CREMENT": 34,
        "BACKTICK": 35,
        "TO": 36,
        "BY": 37,
        "FROM": 38,
        "WITH": 39,
        "FOR": 40,
        "Properties": 41,
        "LABEL": 42,
        "KeyBase": 43,
        "Arg": 44,
        ",": 45,
        "NEWLINE": 46,
        "INDENT": 47,
        "...": 48,
        "Lines": 49,
        "Line": 50,
        "<-": 51,
        "COMMENT": 52,
        "REQUIRE": 53,
        "SplatChain": 54,
        "CLONEPORT": 55,
        "ASSIGN": 56,
        "IMPORT": 57,
        "+-": 58,
        "CLONE": 59,
        "YIELD": 60,
        "COMPARE": 61,
        "LOGIC": 62,
        "MATH": 63,
        "POWER": 64,
        "SHIFT": 65,
        "BITWISE": 66,
        "CONCAT": 67,
        "COMPOSE": 68,
        "RELATION": 69,
        "PIPE": 70,
        "BACKPIPE": 71,
        "!?": 72,
        "->": 73,
        "FUNCTION": 74,
        "GENERATOR": 75,
        "IF": 76,
        "Else": 77,
        "POST_IF": 78,
        "LoopHead": 79,
        "DO": 80,
        "WHILE": 81,
        "CASE": 82,
        "HURL": 83,
        "JUMP": 84,
        "SWITCH": 85,
        "Exprs": 86,
        "Cases": 87,
        "DEFAULT": 88,
        "ELSE": 89,
        "TRY": 90,
        "CATCH": 91,
        "FINALLY": 92,
        "CLASS": 93,
        "OptExtends": 94,
        "OptImplements": 95,
        "EXTENDS": 96,
        "DECL": 97,
        "KeyValue": 98,
        "Property": 99,
        ":": 100,
        "Body": 101,
        "IN": 102,
        "OF": 103,
        "IMPLEMENTS": 104,
        "Root": 105,
        "$accept": 0,
        "$end": 1
      },
      terminals_: {
        2: "error",
        4: "ID",
        7: "STRNUM",
        8: "LITERAL",
        9: "DOT",
        11: "CALL(",
        14: ")CALL",
        15: "?",
        16: "LET",
        18: "[",
        21: "]",
        22: "DEDENT",
        23: "{",
        24: "}",
        25: "(",
        26: "BIOP",
        27: ")",
        28: "BIOPR",
        29: "BIOPBP",
        30: "BIOPP",
        31: "PARAM(",
        32: ")PARAM",
        33: "UNARY",
        34: "CREMENT",
        35: "BACKTICK",
        36: "TO",
        37: "BY",
        38: "FROM",
        39: "WITH",
        40: "FOR",
        42: "LABEL",
        45: ",",
        46: "NEWLINE",
        47: "INDENT",
        48: "...",
        51: "<-",
        52: "COMMENT",
        53: "REQUIRE",
        55: "CLONEPORT",
        56: "ASSIGN",
        57: "IMPORT",
        58: "+-",
        59: "CLONE",
        60: "YIELD",
        61: "COMPARE",
        62: "LOGIC",
        63: "MATH",
        64: "POWER",
        65: "SHIFT",
        66: "BITWISE",
        67: "CONCAT",
        68: "COMPOSE",
        69: "RELATION",
        70: "PIPE",
        71: "BACKPIPE",
        72: "!?",
        73: "->",
        74: "FUNCTION",
        75: "GENERATOR",
        76: "IF",
        78: "POST_IF",
        80: "DO",
        81: "WHILE",
        82: "CASE",
        83: "HURL",
        84: "JUMP",
        85: "SWITCH",
        88: "DEFAULT",
        89: "ELSE",
        90: "TRY",
        91: "CATCH",
        92: "FINALLY",
        93: "CLASS",
        96: "EXTENDS",
        97: "DECL",
        100: ":",
        102: "IN",
        103: "OF",
        104: "IMPLEMENTS"
      },
      productions_: [0, [3, 1], [3, 1], [3, 1], [3, 1], [3, 1], [3, 3], [3, 3], [3, 5], [3, 2], [3, 6], [3, 4], [3, 5], [3, 7], [3, 3], [3, 4], [3, 4], [3, 3], [3, 4], [3, 4], [3, 3], [3, 7], [3, 3], [3, 7], [3, 3], [3, 3], [3, 5], [3, 6], [3, 6], [3, 5], [3, 7], [3, 6], [3, 8], [3, 4], [3, 6], [3, 9], [3, 8], [3, 7], [3, 6], [3, 6], [3, 5], [3, 3], [3, 3], [6, 4], [6, 4], [6, 5], [6, 5], [10, 1], [10, 1], [43, 1], [43, 1], [12, 0], [12, 1], [12, 3], [12, 4], [12, 6], [44, 1], [44, 2], [44, 1], [13, 0], [13, 1], [49, 0], [49, 1], [49, 3], [49, 2], [50, 1], [50, 2], [50, 6], [50, 1], [50, 1], [50, 2], [17, 3], [54, 2], [19, 3], [19, 3], [19, 5], [19, 1], [19, 3], [19, 3], [19, 6], [19, 3], [19, 6], [19, 2], [19, 2], [19, 3], [19, 2], [19, 3], [19, 3], [19, 3], [19, 4], [19, 4], [19, 4], [19, 2], [19, 2], [19, 2], [19, 3], [19, 3], [19, 3], [19, 6], [19, 5], [19, 1], [19, 2], [19, 3], [19, 3], [19, 3], [19, 3], [19, 3], [19, 3], [19, 3], [19, 3], [19, 3], [19, 3], [19, 3], [19, 3], [19, 2], [19, 6], [19, 6], [19, 6], [19, 4], [19, 3], [19, 3], [19, 4], [19, 6], [19, 2], [19, 5], [19, 1], [19, 1], [19, 2], [19, 3], [19, 5], [19, 5], [19, 2], [19, 4], [19, 4], [19, 2], [19, 2], [19, 4], [19, 6], [19, 5], [19, 7], [19, 4], [19, 5], [19, 4], [19, 3], [19, 2], [19, 2], [19, 5], [86, 1], [86, 3], [98, 1], [98, 1], [98, 3], [98, 3], [98, 5], [98, 5], [99, 3], [99, 6], [99, 1], [99, 3], [99, 3], [99, 2], [99, 2], [99, 2], [99, 1], [41, 0], [41, 1], [41, 3], [41, 4], [41, 4], [5, 3], [101, 1], [101, 1], [101, 3], [77, 0], [77, 2], [77, 5], [79, 4], [79, 6], [79, 6], [79, 8], [79, 2], [79, 4], [79, 4], [79, 6], [79, 4], [79, 6], [79, 6], [79, 8], [79, 6], [79, 5], [79, 8], [79, 7], [79, 8], [79, 7], [79, 10], [79, 9], [79, 10], [79, 9], [79, 2], [79, 4], [79, 4], [79, 6], [20, 1], [20, 2], [20, 3], [20, 3], [87, 3], [87, 4], [94, 2], [94, 0], [95, 2], [95, 0], [105, 1]],
      performAction: function anonymous(yytext, yyleng, yylineno, yy, yystate, $$, _$) {
        var $0 = $$.length - 1;
        switch (yystate) {
          case 1:
            this.$ = yy.L(_$[$0], _$[$0], yy.Chain(yy.L(_$[$0], _$[$0], yy.Var($$[$0]))));
            break;
          case 2:
          case 3:
            this.$ = yy.L(_$[$0], _$[$0], yy.Chain($$[$0]));
            break;
          case 4:
          case 5:
            this.$ = yy.L(_$[$0], _$[$0], yy.Chain(yy.L(_$[$0], _$[$0], yy.Literal($$[$0]))));
            break;
          case 6:
          case 7:
            this.$ = yy.L(_$[$0 - 2], _$[$0], $$[$0 - 2].add(yy.L(_$[$0 - 1], _$[$0], yy.Index($$[$0], $$[$0 - 1], true))));
            break;
          case 8:
            this.$ = yy.L(_$[$0 - 4], _$[$0], $$[$0 - 4].add(yy.L(_$[$0 - 3], _$[$0], yy.Call($$[$0 - 2]))));
            break;
          case 9:
            this.$ = yy.L(_$[$0 - 1], _$[$0], yy.Chain(yy.L(_$[$0 - 1], _$[$0], yy.Existence($$[$0 - 1].unwrap()))));
            break;
          case 10:
            this.$ = yy.L(_$[$0 - 5], _$[$0], yy.Chain(yy.L(_$[$0 - 5], _$[$0 - 1], yy.Call['let']($$[$0 - 3], $$[$0]))));
            break;
          case 11:
            this.$ = yy.L(_$[$0 - 3], _$[$0], yy.Chain(yy.L(_$[$0 - 3], _$[$0], $$[$0 - 1][0].makeComprehension($$[$0 - 2], $$[$0 - 1].slice(1)))));
            break;
          case 12:
            this.$ = yy.L(_$[$0 - 4], _$[$0], yy.Chain(yy.L(_$[$0 - 4], _$[$0], $$[$0 - 2][0].makeComprehension($$[$0 - 3], $$[$0 - 2].slice(1)))));
            break;
          case 13:
            this.$ = yy.L(_$[$0 - 6], _$[$0], yy.Chain(yy.L(_$[$0 - 6], _$[$0], $$[$0 - 1][0].addObjComp().makeComprehension(yy.L(_$[$0 - 4], _$[$0 - 4], yy.Arr($$[$0 - 4])), $$[$0 - 1].slice(1)))));
            break;
          case 14:
          case 20:
          case 22:
            this.$ = yy.L(_$[$0 - 2], _$[$0], yy.Chain(yy.L(_$[$0 - 1], _$[$0 - 1], yy.Binary($$[$0 - 1]))));
            break;
          case 15:
            this.$ = yy.L(_$[$0 - 3], _$[$0], yy.Chain(yy.L(_$[$0 - 2], _$[$0 - 2], yy.Binary($$[$0 - 2], void 8, $$[$0 - 1]))));
            break;
          case 16:
            this.$ = yy.L(_$[$0 - 3], _$[$0], yy.Chain(yy.L(_$[$0 - 1], _$[$0 - 1], yy.Binary($$[$0 - 1], $$[$0 - 2]))));
            break;
          case 17:
            this.$ = yy.L(_$[$0 - 2], _$[$0], yy.Chain(yy.L(_$[$0 - 1], _$[$0 - 1], '!' === $$[$0 - 1].charAt(0) ? yy.Binary($$[$0 - 1].slice(1)).invertIt() : yy.Binary($$[$0 - 1]))));
            break;
          case 18:
            this.$ = yy.L(_$[$0 - 3], _$[$0], yy.Chain(yy.L(_$[$0 - 2], _$[$0 - 2], '!' === $$[$0 - 2].charAt(0) ? yy.Binary($$[$0 - 2].slice(1), void 8, $$[$0 - 1]).invertIt() : yy.Binary($$[$0 - 2], void 8, $$[$0 - 1]))));
            break;
          case 19:
            this.$ = yy.L(_$[$0 - 3], _$[$0], yy.Chain(yy.L(_$[$0 - 1], _$[$0 - 1], '!' === $$[$0 - 1].charAt(0) ? yy.Binary($$[$0 - 1].slice(1), $$[$0 - 2]).invertIt() : yy.Binary($$[$0 - 1], $$[$0 - 2]))));
            break;
          case 21:
            this.$ = yy.L(_$[$0 - 6], _$[$0], yy.Chain(yy.L(_$[$0 - 5], _$[$0 - 5], yy.Binary($$[$0 - 5], void 8, $$[$0 - 3]))));
            break;
          case 23:
            this.$ = yy.L(_$[$0 - 6], _$[$0], yy.Chain(yy.L(_$[$0 - 1], _$[$0 - 1], yy.Binary($$[$0 - 1], $$[$0 - 4]))));
            break;
          case 24:
          case 25:
            this.$ = yy.L(_$[$0 - 2], _$[$0], yy.Chain(yy.L(_$[$0 - 1], _$[$0 - 1], yy.Unary($$[$0 - 1]))));
            break;
          case 26:
            this.$ = yy.L(_$[$0 - 4], _$[$0], yy.Chain($$[$0 - 2]));
            break;
          case 27:
            this.$ = yy.L(_$[$0 - 5], _$[$0], yy.Chain(yy.L(_$[$0 - 4], _$[$0 - 1], $$[$0 - 2].add(yy.L(_$[$0 - 4], _$[$0 - 4], yy.Call([$$[$0 - 4]]))))));
            break;
          case 28:
            this.$ = yy.L(_$[$0 - 5], _$[$0], yy.Chain(yy.L(_$[$0 - 3], _$[$0 - 3], yy.Chain(yy.Var('flip$'))).add(yy.L(_$[$0 - 3], _$[$0 - 3], yy.Call([$$[$0 - 3]])))).flipIt().add(yy.L(_$[$0 - 1], _$[$0 - 1], yy.Call([$$[$0 - 1]]))));
            break;
          case 29:
            this.$ = yy.L(_$[$0 - 4], _$[$0], yy.Chain(yy.L(_$[$0 - 3], _$[$0 - 1], new yy.For({
              from: $$[$0 - 3],
              op: $$[$0 - 2],
              to: $$[$0 - 1],
              inComprehension: true
            }))));
            break;
          case 30:
            this.$ = yy.L(_$[$0 - 6], _$[$0], yy.Chain(yy.L(_$[$0 - 5], _$[$0 - 1], new yy.For({
              from: $$[$0 - 5],
              op: $$[$0 - 4],
              to: $$[$0 - 3],
              step: $$[$0 - 1],
              inComprehension: true
            }))));
            break;
          case 31:
            this.$ = yy.L(_$[$0 - 5], _$[$0], yy.Chain(yy.L(_$[$0 - 4], _$[$0 - 1], new yy.For({
              from: $$[$0 - 3],
              op: $$[$0 - 2],
              to: $$[$0 - 1],
              inComprehension: true
            }))));
            break;
          case 32:
            this.$ = yy.L(_$[$0 - 7], _$[$0], yy.Chain(yy.L(_$[$0 - 6], _$[$0 - 1], new yy.For({
              from: $$[$0 - 5],
              op: $$[$0 - 4],
              to: $$[$0 - 3],
              step: $$[$0 - 1],
              inComprehension: true
            }))));
            break;
          case 33:
            this.$ = yy.L(_$[$0 - 3], _$[$0], yy.Chain(yy.L(_$[$0 - 2], _$[$0 - 1], new yy.For({
              from: yy.Chain(yy.Literal(0)),
              op: $$[$0 - 2],
              to: $$[$0 - 1],
              inComprehension: true
            }))));
            break;
          case 34:
            this.$ = yy.L(_$[$0 - 5], _$[$0], yy.Chain(yy.L(_$[$0 - 4], _$[$0 - 1], new yy.For({
              from: yy.Chain(yy.Literal(0)),
              op: $$[$0 - 4],
              to: $$[$0 - 3],
              step: $$[$0 - 1],
              inComprehension: true
            }))));
            break;
          case 35:
            this.$ = yy.L(_$[$0 - 8], _$[$0], yy.Chain(yy.L(_$[$0 - 8], _$[$0], new yy.StepSlice({
              op: $$[$0 - 4],
              target: $$[$0 - 8],
              from: $$[$0 - 5],
              to: $$[$0 - 3],
              step: $$[$0 - 1]
            }))));
            break;
          case 36:
            this.$ = yy.L(_$[$0 - 7], _$[$0], yy.Chain(yy.L(_$[$0 - 7], _$[$0], new yy.StepSlice({
              op: $$[$0 - 4],
              target: $$[$0 - 7],
              from: yy.Literal(0),
              to: $$[$0 - 3],
              step: $$[$0 - 1]
            }))));
            break;
          case 37:
            this.$ = yy.L(_$[$0 - 6], _$[$0], yy.Chain(yy.L(_$[$0 - 6], _$[$0], yy.Slice({
              type: $$[$0 - 2],
              target: $$[$0 - 6],
              from: $$[$0 - 3],
              to: $$[$0 - 1]
            }))));
            break;
          case 38:
            this.$ = yy.L(_$[$0 - 5], _$[$0], yy.Chain(yy.L(_$[$0 - 5], _$[$0], yy.Slice({
              type: $$[$0 - 1],
              target: $$[$0 - 5],
              from: $$[$0 - 2]
            }))));
            break;
          case 39:
            this.$ = yy.L(_$[$0 - 5], _$[$0], yy.Chain(yy.L(_$[$0 - 5], _$[$0], yy.Slice({
              type: $$[$0 - 2],
              target: $$[$0 - 5],
              to: $$[$0 - 1]
            }))));
            break;
          case 40:
            this.$ = yy.L(_$[$0 - 4], _$[$0], yy.Chain(yy.L(_$[$0 - 4], _$[$0], yy.Slice({
              type: $$[$0 - 1],
              target: $$[$0 - 4]
            }))));
            break;
          case 41:
            this.$ = yy.L(_$[$0 - 2], _$[$0], yy.Chain(yy.L(_$[$0 - 2], _$[$0 - 1], yy.Cascade($$[$0 - 1], $$[$0], 'with'))));
            break;
          case 42:
            this.$ = yy.L(_$[$0 - 2], _$[$0], yy.Chain(yy.L(_$[$0 - 2], _$[$0 - 1], new yy.For({
              kind: $$[$0 - 2],
              source: $$[$0 - 1],
              body: $$[$0],
              ref: true
            }).addBody($$[$0]))));
            break;
          case 43:
            this.$ = yy.L(_$[$0 - 3], _$[$0], yy.Arr($$[$0 - 2]));
            break;
          case 44:
            this.$ = yy.L(_$[$0 - 3], _$[$0], yy.Obj($$[$0 - 2]));
            break;
          case 45:
            this.$ = yy.L(_$[$0 - 4], _$[$0], yy.Arr($$[$0 - 3]).named($$[$0]));
            break;
          case 46:
            this.$ = yy.L(_$[$0 - 4], _$[$0], yy.Obj($$[$0 - 3]).named($$[$0]));
            break;
          case 47:
          case 48:
          case 56:
          case 59:
          case 60:
          case 64:
          case 65:
          case 149:
          case 157:
          case 170:
          case 171:
            break;
          case 49:
            this.$ = yy.L(_$[$0], _$[$0], yy.Key($$[$0]));
            break;
          case 50:
            this.$ = yy.L(_$[$0], _$[$0], yy.Literal($$[$0]));
            break;
          case 51:
          case 164:
            this.$ = yy.L(_$[$0], _$[$0], []);
            break;
          case 52:
          case 147:
          case 165:
          case 202:
            this.$ = yy.L(_$[$0], _$[$0], [$$[$0]]);
            break;
          case 53:
          case 148:
          case 166:
          case 204:
          case 205:
            this.$ = yy.L(_$[$0 - 2], _$[$0], $$[$0 - 2].concat($$[$0]));
            break;
          case 54:
          case 167:
            this.$ = yy.L(_$[$0 - 3], _$[$0], $$[$0 - 3].concat($$[$0]));
            break;
          case 55:
            this.$ = yy.L(_$[$0 - 5], _$[$0 - 2], $$[$0 - 5].concat($$[$0 - 2]));
            break;
          case 57:
          case 162:
            this.$ = yy.L(_$[$0 - 1], _$[$0], yy.Splat($$[$0]));
            break;
          case 58:
            this.$ = yy.L(_$[$0], _$[$0], yy.Splat(yy.L(_$[$0], _$[$0], yy.Arr()), true));
            break;
          case 61:
            this.$ = yy.L(_$[$0], _$[$0], yy.Block());
            break;
          case 62:
            this.$ = yy.L(_$[$0], _$[$0], yy.Block($$[$0]));
            break;
          case 63:
          case 172:
            this.$ = yy.L(_$[$0 - 2], _$[$0], $$[$0 - 2].add($$[$0]));
            break;
          case 66:
            this.$ = yy.L(_$[$0 - 1], _$[$0], yy.Cascade($$[$0 - 1], $$[$0], 'cascade'));
            break;
          case 67:
            this.$ = yy.L(_$[$0 - 5], _$[$0], yy.Call.back($$[$0 - 4], $$[$0], /~/.test($$[$0 - 1]), /--|~~/.test($$[$0 - 1]), /!/.test($$[$0 - 1]), /\*/.test($$[$0 - 1])));
            break;
          case 68:
          case 163:
            this.$ = yy.L(_$[$0], _$[$0], yy.JS($$[$0], true, true));
            break;
          case 69:
            this.$ = yy.L(_$[$0], _$[$0], yy.Throw(yy.L(_$[$0], _$[$0], yy.JS("Error('unimplemented')"))));
            break;
          case 70:
            this.$ = yy.L(_$[$0 - 1], _$[$0], yy.Require($$[$0].unwrap()));
            break;
          case 71:
            this.$ = yy.L(_$[$0 - 2], _$[$0], $$[$0 - 1]);
            break;
          case 72:
            this.$ = yy.L(_$[$0 - 1], _$[$0], yy.Splat($$[$0].unwrap()));
            break;
          case 73:
            this.$ = yy.L(_$[$0 - 2], _$[$0], yy.Import(yy.L(_$[$0 - 2], _$[$0 - 1], yy.Unary('^^', $$[$0 - 2], {prec: 'yy.UNARY'})), $$[$0], false));
            break;
          case 74:
            this.$ = yy.L(_$[$0 - 2], _$[$0], yy.Import(yy.L(_$[$0 - 2], _$[$0 - 1], yy.Unary('^^', $$[$0 - 2], {prec: 'yy.UNARY'})), $$[$0].unwrap(), false));
            break;
          case 75:
            this.$ = yy.L(_$[$0 - 4], _$[$0], $$[$0 - 2].add(yy.L(_$[$0 - 4], _$[$0], yy.Call([$$[$0 - 4], $$[$0]]))));
            break;
          case 76:
            this.$ = yy.L(_$[$0], _$[$0], $$[$0].unwrap());
            break;
          case 77:
            this.$ = yy.L(_$[$0 - 2], _$[$0], yy.Assign($$[$0 - 2].unwrap(), $$[$0], yy.L(_$[$0 - 1], _$[$0 - 1], yy.Box($$[$0 - 1]))));
            break;
          case 78:
            this.$ = yy.L(_$[$0 - 2], _$[$0], yy.Assign($$[$0 - 2], $$[$0], yy.L(_$[$0 - 1], _$[$0 - 1], yy.Box($$[$0 - 1]))));
            break;
          case 79:
            this.$ = yy.L(_$[$0 - 5], _$[$0], yy.Assign($$[$0 - 5].unwrap(), yy.Arr.maybe($$[$0 - 2]), yy.L(_$[$0 - 4], _$[$0 - 4], yy.Box($$[$0 - 4]))));
            break;
          case 80:
            this.$ = yy.L(_$[$0 - 2], _$[$0], yy.Import($$[$0 - 2], $$[$0], $$[$0 - 1] === '<<<<'));
            break;
          case 81:
            this.$ = yy.L(_$[$0 - 5], _$[$0], yy.Import($$[$0 - 5], yy.Arr.maybe($$[$0 - 2]), $$[$0 - 4] === '<<<<'));
            break;
          case 82:
            this.$ = yy.L(_$[$0 - 1], _$[$0], yy.Unary($$[$0 - 1], $$[$0].unwrap()));
            break;
          case 83:
            this.$ = yy.L(_$[$0 - 1], _$[$0], yy.Unary($$[$0], $$[$0 - 1].unwrap(), true));
            break;
          case 84:
            this.$ = yy.L(_$[$0 - 2], _$[$0], yy.Unary($$[$0 - 2], yy.Splat($$[$0].unwrap())));
            break;
          case 85:
            this.$ = yy.L(_$[$0 - 1], _$[$0], yy.Unary($$[$0], $$[$0 - 1], true));
            break;
          case 86:
          case 87:
          case 88:
            this.$ = yy.L(_$[$0 - 2], _$[$0], yy.Assign($$[$0].unwrap(), [$$[$0 - 2]], yy.L(_$[$0 - 1], _$[$0 - 1], yy.Box($$[$0 - 1]))));
            break;
          case 89:
          case 90:
          case 91:
            this.$ = yy.L(_$[$0 - 3], _$[$0], yy.Assign(yy.Splat($$[$0].unwrap()), [$$[$0 - 3]], yy.L(_$[$0 - 2], _$[$0 - 2], yy.Box($$[$0 - 2]))));
            break;
          case 92:
          case 93:
          case 94:
            this.$ = yy.L(_$[$0 - 1], _$[$0], yy.Unary($$[$0 - 1], $$[$0]));
            break;
          case 95:
          case 96:
          case 97:
            this.$ = yy.L(_$[$0 - 2], _$[$0], yy.Unary($$[$0 - 2], yy.Splat($$[$0])));
            break;
          case 98:
            this.$ = yy.L(_$[$0 - 5], _$[$0], yy.Unary($$[$0 - 5], yy.Splat(yy.Arr($$[$0 - 2]))));
            break;
          case 99:
            this.$ = yy.L(_$[$0 - 4], _$[$0], yy.Unary($$[$0 - 4], yy.Arr.maybe($$[$0 - 2])));
            break;
          case 100:
            this.$ = yy.L(_$[$0], _$[$0], yy.Yield($$[$0]));
            break;
          case 101:
            this.$ = yy.L(_$[$0 - 1], _$[$0], yy.Yield($$[$0 - 1], $$[$0]));
            break;
          case 102:
          case 103:
          case 104:
          case 105:
          case 106:
          case 107:
          case 108:
          case 109:
          case 110:
          case 158:
            this.$ = (yy.L(_$[$0 - 1], _$[$0 - 1], yy.Binary($$[$0 - 1], $$[$0 - 2], $$[$0])));
            break;
          case 111:
            this.$ = yy.L(_$[$0 - 2], _$[$0], '!' === $$[$0 - 1].charAt(0) ? yy.Binary($$[$0 - 1].slice(1), $$[$0 - 2], $$[$0]).invert() : yy.Binary($$[$0 - 1], $$[$0 - 2], $$[$0]));
            break;
          case 112:
            this.$ = yy.L(_$[$0 - 2], _$[$0], yy.Block($$[$0 - 2]).pipe($$[$0], $$[$0 - 1]));
            break;
          case 113:
            this.$ = yy.L(_$[$0 - 2], _$[$0], yy.Block($$[$0 - 2]).pipe([$$[$0]], $$[$0 - 1]));
            break;
          case 114:
            this.$ = yy.L(_$[$0 - 1], _$[$0], yy.Existence($$[$0 - 1].unwrap(), true));
            break;
          case 115:
            this.$ = yy.L(_$[$0 - 5], _$[$0], yy.Fun($$[$0 - 4], $$[$0], /~/.test($$[$0 - 1]), /--|~~/.test($$[$0 - 1]), /!/.test($$[$0 - 1]), /\*/.test($$[$0 - 1])));
            break;
          case 116:
            this.$ = yy.L(_$[$0 - 5], _$[$0], yy.Fun($$[$0 - 3], $$[$0]).named($$[$0 - 5]));
            break;
          case 117:
            this.$ = yy.L(_$[$0 - 5], _$[$0], yy.Fun($$[$0 - 3], $$[$0], false, false, false, true).named($$[$0 - 5]));
            break;
          case 118:
            this.$ = (yy.L(_$[$0 - 3], _$[$0 - 2], yy.If($$[$0 - 2], $$[$0 - 1], $$[$0 - 3] === 'unless')).addElse($$[$0]));
            break;
          case 119:
            this.$ = (yy.L(_$[$0 - 1], _$[$0], yy.If($$[$0], $$[$0 - 2], $$[$0 - 1] === 'unless')));
            break;
          case 120:
            this.$ = yy.L(_$[$0 - 2], _$[$0], $$[$0 - 2].addBody($$[$0 - 1]).addElse($$[$0]));
            break;
          case 121:
            this.$ = yy.L(_$[$0 - 3], _$[$0], new yy.While($$[$0], $$[$0 - 1] === 'until', true).addBody($$[$0 - 2]));
            break;
          case 122:
            this.$ = yy.L(_$[$0 - 5], _$[$0], new yy.While($$[$0 - 2], $$[$0 - 3] === 'until', true).addGuard($$[$0]).addBody($$[$0 - 4]));
            break;
          case 123:
            this.$ = yy.L(_$[$0 - 1], _$[$0], yy.Jump[$$[$0 - 1]]($$[$0]));
            break;
          case 124:
            this.$ = yy.L(_$[$0 - 4], _$[$0], yy.Jump[$$[$0 - 4]](yy.Arr.maybe($$[$0 - 2])));
            break;
          case 125:
            this.$ = yy.L(_$[$0], _$[$0], yy.Jump[$$[$0]]());
            break;
          case 126:
            this.$ = yy.L(_$[$0], _$[$0], new yy.Jump($$[$0]));
            break;
          case 127:
            this.$ = yy.L(_$[$0 - 1], _$[$0], new yy.Jump($$[$0 - 1], $$[$0]));
            break;
          case 128:
            this.$ = yy.L(_$[$0 - 2], _$[$0], new yy.Switch($$[$0 - 2], $$[$0 - 1], $$[$0]));
            break;
          case 129:
          case 130:
            this.$ = yy.L(_$[$0 - 4], _$[$0], new yy.Switch($$[$0 - 4], $$[$0 - 3], $$[$0 - 2], $$[$0]));
            break;
          case 131:
            this.$ = yy.L(_$[$0 - 1], _$[$0], new yy.Switch($$[$0 - 1], null, $$[$0]));
            break;
          case 132:
          case 133:
            this.$ = yy.L(_$[$0 - 3], _$[$0], new yy.Switch($$[$0 - 3], null, $$[$0 - 2], $$[$0]));
            break;
          case 134:
            this.$ = yy.L(_$[$0 - 1], _$[$0], new yy.Switch($$[$0 - 1], null, [], $$[$0]));
            break;
          case 135:
            this.$ = yy.L(_$[$0 - 1], _$[$0], new yy.Try($$[$0]));
            break;
          case 136:
            this.$ = yy.L(_$[$0 - 3], _$[$0], new yy.Try($$[$0 - 2], void 8, yy.L(_$[$0 - 1], _$[$0 - 1], $$[$0])));
            break;
          case 137:
            this.$ = yy.L(_$[$0 - 5], _$[$0], new yy.Try($$[$0 - 4], void 8, yy.L(_$[$0 - 3], _$[$0 - 3], $$[$0 - 2]), yy.L(_$[$0 - 1], _$[$0 - 1], $$[$0])));
            break;
          case 138:
            this.$ = yy.L(_$[$0 - 4], _$[$0], new yy.Try($$[$0 - 3], $$[$0 - 1], yy.L(_$[$0 - 2], _$[$0 - 1], $$[$0])));
            break;
          case 139:
            this.$ = yy.L(_$[$0 - 6], _$[$0], new yy.Try($$[$0 - 5], $$[$0 - 3], yy.L(_$[$0 - 4], _$[$0 - 3], $$[$0 - 2]), yy.L(_$[$0 - 1], _$[$0 - 1], $$[$0])));
            break;
          case 140:
            this.$ = yy.L(_$[$0 - 3], _$[$0], new yy.Try($$[$0 - 2], void 8, void 8, yy.L(_$[$0 - 1], _$[$0 - 1], $$[$0])));
            break;
          case 141:
            this.$ = yy.L(_$[$0 - 4], _$[$0], new yy.Class({
              title: $$[$0 - 3].unwrap(),
              sup: $$[$0 - 2],
              mixins: $$[$0 - 1],
              body: $$[$0]
            }));
            break;
          case 142:
            this.$ = yy.L(_$[$0 - 3], _$[$0], new yy.Class({
              sup: $$[$0 - 2],
              mixins: $$[$0 - 1],
              body: $$[$0]
            }));
            break;
          case 143:
            this.$ = yy.L(_$[$0 - 2], _$[$0], yy.Util.Extends($$[$0 - 2].unwrap(), $$[$0]));
            break;
          case 144:
          case 145:
            this.$ = yy.L(_$[$0 - 1], _$[$0], new yy.Label($$[$0 - 1], $$[$0]));
            break;
          case 146:
            this.$ = yy.L(_$[$0 - 4], _$[$0], yy.Decl($$[$0 - 4], $$[$0 - 2], yylineno + 1));
            break;
          case 150:
            this.$ = yy.L(_$[$0], _$[$0], yy.Prop(yy.L(_$[$0], _$[$0], yy.Key($$[$0], $$[$0] !== 'arguments' && $$[$0] !== 'eval')), yy.L(_$[$0], _$[$0], yy.Literal($$[$0]))));
            break;
          case 151:
            this.$ = yy.L(_$[$0 - 2], _$[$0], yy.Prop($$[$0], yy.Chain($$[$0 - 2], [yy.L(_$[$0 - 1], _$[$0], yy.Index($$[$0], $$[$0 - 1]))])));
            break;
          case 152:
            this.$ = yy.L(_$[$0 - 2], _$[$0], yy.Prop($$[$0], yy.Chain(yy.L(_$[$0 - 2], _$[$0 - 2], yy.Literal($$[$0 - 2])), [yy.L(_$[$0 - 1], _$[$0], yy.Index($$[$0], $$[$0 - 1]))])));
            break;
          case 153:
            this.$ = yy.L(_$[$0 - 4], _$[$0], yy.Prop(yy.L(_$[$0], _$[$0], yy.Key($$[$0])), yy.L(_$[$0 - 4], _$[$0 - 1], yy.Obj($$[$0 - 3]).named($$[$0]))));
            break;
          case 154:
            this.$ = yy.L(_$[$0 - 4], _$[$0], yy.Prop(yy.L(_$[$0], _$[$0], yy.Key($$[$0])), yy.L(_$[$0 - 4], _$[$0 - 1], yy.Arr($$[$0 - 3]).named($$[$0]))));
            break;
          case 155:
            this.$ = yy.L(_$[$0 - 2], _$[$0], yy.Prop($$[$0 - 2], $$[$0]));
            break;
          case 156:
            this.$ = yy.L(_$[$0 - 5], _$[$0], yy.Prop($$[$0 - 5], yy.Arr.maybe($$[$0 - 2])));
            break;
          case 159:
            this.$ = (yy.L(_$[$0 - 1], _$[$0 - 1], yy.Binary($$[$0 - 1], $$[$0 - 2], $$[$0], true)));
            break;
          case 160:
            this.$ = yy.L(_$[$0 - 1], _$[$0], yy.Prop($$[$0].maybeKey(), yy.L(_$[$0 - 1], _$[$0 - 1], yy.Literal($$[$0 - 1] === '+'))));
            break;
          case 161:
            this.$ = yy.L(_$[$0 - 1], _$[$0], yy.Prop(yy.L(_$[$0], _$[$0], yy.Key($$[$0], true)), yy.L(_$[$0 - 1], _$[$0 - 1], yy.Literal($$[$0 - 1] === '+'))));
            break;
          case 168:
            this.$ = yy.L(_$[$0 - 3], _$[$0], $$[$0 - 2]);
            break;
          case 169:
            this.$ = yy.L(_$[$0 - 2], _$[$0], yy.Parens($$[$0 - 1].chomp().unwrap(), false, $$[$0 - 2] === '"', yy.L(_$[$0 - 2], _$[$0 - 2], {}), yy.L(_$[$0], _$[$0], {})));
            break;
          case 173:
          case 209:
          case 211:
            this.$ = yy.L(_$[$0], _$[$0], null);
            break;
          case 174:
          case 208:
          case 210:
            this.$ = yy.L(_$[$0 - 1], _$[$0], $$[$0]);
            break;
          case 175:
            this.$ = yy.L(_$[$0 - 4], _$[$0], yy.If($$[$0 - 2], $$[$0 - 1], $$[$0 - 3] === 'unless').addElse($$[$0]));
            break;
          case 176:
            this.$ = yy.L(_$[$0 - 3], _$[$0], new yy.For({
              kind: $$[$0 - 3],
              item: $$[$0 - 2].unwrap(),
              index: $$[$0 - 1],
              source: $$[$0]
            }));
            break;
          case 177:
            this.$ = yy.L(_$[$0 - 5], _$[$0], new yy.For({
              kind: $$[$0 - 5],
              item: $$[$0 - 4].unwrap(),
              index: $$[$0 - 3],
              source: $$[$0 - 2],
              guard: $$[$0]
            }));
            break;
          case 178:
            this.$ = yy.L(_$[$0 - 5], _$[$0], new yy.For({
              kind: $$[$0 - 5],
              item: $$[$0 - 4].unwrap(),
              index: $$[$0 - 3],
              source: $$[$0 - 2],
              step: $$[$0]
            }));
            break;
          case 179:
            this.$ = yy.L(_$[$0 - 7], _$[$0], new yy.For({
              kind: $$[$0 - 7],
              item: $$[$0 - 6].unwrap(),
              index: $$[$0 - 5],
              source: $$[$0 - 4],
              step: $$[$0 - 2],
              guard: $$[$0]
            }));
            break;
          case 180:
            this.$ = yy.L(_$[$0 - 1], _$[$0], new yy.For({
              kind: $$[$0 - 1],
              source: $$[$0],
              ref: true
            }));
            break;
          case 181:
            this.$ = yy.L(_$[$0 - 3], _$[$0], new yy.For({
              kind: $$[$0 - 3],
              source: $$[$0 - 2],
              ref: true,
              guard: $$[$0]
            }));
            break;
          case 182:
            this.$ = yy.L(_$[$0 - 3], _$[$0], new yy.For({
              kind: $$[$0 - 3],
              source: $$[$0 - 2],
              ref: true,
              step: $$[$0]
            }));
            break;
          case 183:
            this.$ = yy.L(_$[$0 - 5], _$[$0], new yy.For({
              kind: $$[$0 - 5],
              source: $$[$0 - 4],
              ref: true,
              step: $$[$0 - 2],
              guard: $$[$0]
            }));
            break;
          case 184:
            this.$ = yy.L(_$[$0 - 3], _$[$0], new yy.For({
              object: true,
              kind: $$[$0 - 3],
              index: $$[$0 - 2],
              source: $$[$0]
            }));
            break;
          case 185:
            this.$ = yy.L(_$[$0 - 5], _$[$0], new yy.For({
              object: true,
              kind: $$[$0 - 5],
              index: $$[$0 - 4],
              source: $$[$0 - 2],
              guard: $$[$0]
            }));
            break;
          case 186:
            this.$ = yy.L(_$[$0 - 5], _$[$0], new yy.For({
              object: true,
              kind: $$[$0 - 5],
              index: $$[$0 - 4],
              item: $$[$0 - 2].unwrap(),
              source: $$[$0]
            }));
            break;
          case 187:
            this.$ = yy.L(_$[$0 - 7], _$[$0], new yy.For({
              object: true,
              kind: $$[$0 - 7],
              index: $$[$0 - 6],
              item: $$[$0 - 4].unwrap(),
              source: $$[$0 - 2],
              guard: $$[$0]
            }));
            break;
          case 188:
            this.$ = yy.L(_$[$0 - 5], _$[$0], new yy.For({
              kind: $$[$0 - 5],
              index: $$[$0 - 4],
              from: $$[$0 - 2],
              op: $$[$0 - 1],
              to: $$[$0]
            }));
            break;
          case 189:
            this.$ = yy.L(_$[$0 - 4], _$[$0], new yy.For({
              kind: $$[$0 - 4],
              from: $$[$0 - 2],
              op: $$[$0 - 1],
              to: $$[$0],
              ref: true
            }));
            break;
          case 190:
            this.$ = yy.L(_$[$0 - 7], _$[$0], new yy.For({
              kind: $$[$0 - 7],
              index: $$[$0 - 6],
              from: $$[$0 - 4],
              op: $$[$0 - 3],
              to: $$[$0 - 2],
              guard: $$[$0]
            }));
            break;
          case 191:
            this.$ = yy.L(_$[$0 - 6], _$[$0], new yy.For({
              kind: $$[$0 - 6],
              from: $$[$0 - 4],
              op: $$[$0 - 3],
              to: $$[$0 - 2],
              guard: $$[$0],
              ref: true
            }));
            break;
          case 192:
            this.$ = yy.L(_$[$0 - 7], _$[$0], new yy.For({
              kind: $$[$0 - 7],
              index: $$[$0 - 6],
              from: $$[$0 - 4],
              op: $$[$0 - 3],
              to: $$[$0 - 2],
              step: $$[$0]
            }));
            break;
          case 193:
            this.$ = yy.L(_$[$0 - 6], _$[$0], new yy.For({
              kind: $$[$0 - 6],
              from: $$[$0 - 4],
              op: $$[$0 - 3],
              to: $$[$0 - 2],
              step: $$[$0],
              ref: true
            }));
            break;
          case 194:
            this.$ = yy.L(_$[$0 - 9], _$[$0], new yy.For({
              kind: $$[$0 - 9],
              index: $$[$0 - 8],
              from: $$[$0 - 6],
              op: $$[$0 - 5],
              to: $$[$0 - 4],
              step: $$[$0 - 2],
              guard: $$[$0]
            }));
            break;
          case 195:
            this.$ = yy.L(_$[$0 - 8], _$[$0], new yy.For({
              kind: $$[$0 - 8],
              from: $$[$0 - 6],
              op: $$[$0 - 5],
              to: $$[$0 - 4],
              step: $$[$0 - 2],
              guard: $$[$0],
              ref: true
            }));
            break;
          case 196:
            this.$ = yy.L(_$[$0 - 9], _$[$0], new yy.For({
              kind: $$[$0 - 9],
              index: $$[$0 - 8],
              from: $$[$0 - 6],
              op: $$[$0 - 5],
              to: $$[$0 - 4],
              guard: $$[$0 - 2],
              step: $$[$0]
            }));
            break;
          case 197:
            this.$ = yy.L(_$[$0 - 8], _$[$0], new yy.For({
              kind: $$[$0 - 8],
              from: $$[$0 - 6],
              op: $$[$0 - 5],
              to: $$[$0 - 4],
              guard: $$[$0 - 2],
              step: $$[$0],
              ref: true
            }));
            break;
          case 198:
            this.$ = yy.L(_$[$0 - 1], _$[$0], new yy.While($$[$0], $$[$0 - 1] === 'until'));
            break;
          case 199:
            this.$ = yy.L(_$[$0 - 3], _$[$0], new yy.While($$[$0 - 2], $$[$0 - 3] === 'until').addGuard($$[$0]));
            break;
          case 200:
            this.$ = yy.L(_$[$0 - 3], _$[$0], new yy.While($$[$0 - 2], $$[$0 - 3] === 'until', $$[$0]));
            break;
          case 201:
            this.$ = yy.L(_$[$0 - 5], _$[$0], new yy.While($$[$0 - 4], $$[$0 - 5] === 'until', $$[$0 - 2]).addGuard($$[$0]));
            break;
          case 203:
            this.$ = yy.L(_$[$0 - 1], _$[$0], $$[$0 - 1].concat($$[$0]));
            break;
          case 206:
            this.$ = yy.L(_$[$0 - 2], _$[$0], [yy.L(_$[$0 - 2], _$[$0 - 1], new yy.Case($$[$0 - 1], $$[$0]))]);
            break;
          case 207:
            this.$ = yy.L(_$[$0 - 3], _$[$0], $$[$0 - 3].concat(yy.L(_$[$0 - 2], _$[$0 - 1], new yy.Case($$[$0 - 1], $$[$0]))));
            break;
          case 212:
            return this.$;
            break;
        }
      },
      table: [o([1, 46], $V0, {
        105: 1,
        101: 2,
        49: 3,
        17: 4,
        50: 5,
        19: 7,
        3: 12,
        54: 13,
        79: 22,
        5: 32,
        6: 33,
        4: $V1,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        23: $V6,
        25: $V7,
        31: $V8,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        47: $Ve,
        48: $Vf,
        52: $Vg,
        53: $Vh,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }), {1: [3]}, {1: [2, 212]}, o($Vt, [2, 170], {46: $Vw}), o($Vt, [2, 171], {46: [1, 44]}), o($Vx, [2, 62]), o($Vy, $V0, {
        50: 5,
        19: 7,
        3: 12,
        54: 13,
        79: 22,
        5: 32,
        6: 33,
        49: 45,
        4: $V1,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        23: $V6,
        25: $V7,
        31: $V8,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $Vf,
        52: $Vg,
        53: $Vh,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }), o($Vx, $Vz, {
        17: 46,
        35: $VA,
        47: $Ve,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO
      }), o($VP, $VQ, {
        3: 12,
        54: 13,
        79: 22,
        5: 32,
        6: 33,
        12: 62,
        44: 63,
        19: 64,
        4: $V1,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $VS,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }), o($Vx, [2, 68]), o($Vx, [2, 69], {
        5: 32,
        6: 33,
        3: 67,
        4: $V1,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        23: $V6,
        25: $V7,
        39: $Vb,
        40: $VT
      }), {
        3: 69,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        23: $V6,
        25: $V7,
        39: $Vb,
        40: $VT
      }, o($VU, $VV, {
        9: $VW,
        11: $VX,
        15: $VY,
        34: $VZ,
        55: $V_,
        56: $V$,
        72: $V01,
        96: $V11
      }), {
        34: [1, 79],
        56: [1, 78]
      }, {
        3: 80,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        23: $V6,
        25: $V7,
        39: $Vb,
        40: $VT,
        48: $V21
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 83,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        47: $V31,
        48: $V41,
        54: 13,
        56: $V51,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 87,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: [1, 88],
        54: 13,
        56: [1, 86],
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 90,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: [1, 91],
        54: 13,
        56: [1, 89],
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, o([1, 14, 21, 22, 24, 26, 27, 28, 32, 35, 36, 37, 45, 46, 47, 57, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 78, 82, 104], [2, 100], {
        3: 12,
        54: 13,
        79: 22,
        5: 32,
        6: 33,
        19: 92,
        4: $V1,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }), {11: [1, 94]}, {11: [1, 95]}, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 96,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        17: 97,
        47: $Ve
      }, {
        17: 98,
        47: $Ve
      }, o([1, 14, 21, 22, 24, 26, 27, 28, 32, 35, 36, 37, 45, 46, 57, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 78, 82, 104], [2, 125], {
        3: 12,
        54: 13,
        79: 22,
        5: 32,
        6: 33,
        19: 99,
        4: $V1,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        47: [1, 100],
        48: $V61,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }), o($VU, [2, 126], {4: [1, 101]}), {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        17: 104,
        18: $V5,
        19: 105,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        47: $Ve,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        82: $V71,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        86: 102,
        87: 103,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        17: 107,
        47: $Ve
      }, o($V81, $V91, {
        5: 32,
        6: 33,
        3: 108,
        94: 109,
        4: $V1,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        23: $V6,
        25: $V7,
        39: $Vb,
        40: $VT,
        96: $Va1
      }), {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        17: 112,
        18: $V5,
        19: 111,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        47: $Ve,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {47: [1, 113]}, o([1, 9, 11, 14, 15, 21, 22, 24, 26, 27, 28, 32, 34, 35, 36, 37, 40, 45, 46, 47, 55, 56, 57, 58, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 78, 81, 82, 96, 103, 104], $Vb1), o($Vc1, [2, 2]), o($Vc1, [2, 3]), o($Vc1, [2, 4]), o($Vc1, [2, 5]), {11: [1, 114]}, o($Vd1, $VQ, {
        3: 12,
        54: 13,
        79: 22,
        5: 32,
        6: 33,
        44: 63,
        19: 115,
        12: 118,
        4: $V1,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        36: [1, 117],
        38: [1, 116],
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $VS,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }), o($Ve1, $Vf1, {
        41: 120,
        99: 121,
        10: 123,
        98: 124,
        43: 128,
        5: 129,
        4: $Vg1,
        7: $Vh1,
        8: $Vi1,
        18: [1, 119],
        23: $Vj1,
        25: $Vk1,
        47: $Vl1,
        48: $Vm1,
        52: $Vn1,
        58: $Vo1
      }), o($Vp1, $V0, {
        49: 3,
        17: 4,
        50: 5,
        3: 12,
        54: 13,
        79: 22,
        5: 32,
        6: 33,
        19: 136,
        101: 144,
        4: $V1,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        23: $V6,
        25: $V7,
        26: [1, 135],
        28: [1, 137],
        29: [1, 138],
        30: [1, 139],
        31: [1, 140],
        33: [1, 141],
        34: [1, 142],
        35: [1, 143],
        39: $Vb,
        40: $Vc,
        42: $Vd,
        47: $Ve,
        48: $Vf,
        52: $Vg,
        53: $Vh,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }), {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 145,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        3: 147,
        4: $Vq1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 146,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        38: $Vr1,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 150,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, o($Vx, [2, 64], {
        19: 7,
        3: 12,
        54: 13,
        79: 22,
        5: 32,
        6: 33,
        50: 151,
        4: $V1,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        23: $V6,
        25: $V7,
        31: $V8,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $Vf,
        52: $Vg,
        53: $Vh,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }), o([1, 27, 46], $V0, {
        50: 5,
        19: 7,
        3: 12,
        54: 13,
        79: 22,
        5: 32,
        6: 33,
        49: 152,
        4: $V1,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        23: $V6,
        25: $V7,
        31: $V8,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $Vf,
        52: $Vg,
        53: $Vh,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }), {
        22: [1, 153],
        46: $Vw
      }, o($Vx, [2, 66]), {
        3: 154,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        23: $V6,
        25: $V7,
        39: $Vb,
        40: $VT
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 155,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        47: [1, 156],
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 157,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 158,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 159,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 160,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 161,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 162,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 163,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 164,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 165,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 166,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 167,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 168,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 169,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, o($Vs1, $Vt1, {
        13: 170,
        45: $Vu1
      }), o($Vv1, [2, 52]), o($Vv1, $Vw1, {
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO
      }), o($Vv1, [2, 58], {
        54: 13,
        79: 22,
        5: 32,
        6: 33,
        19: 172,
        3: 173,
        4: $V1,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }), o($VP, $VQ, {
        3: 12,
        54: 13,
        79: 22,
        5: 32,
        6: 33,
        44: 63,
        19: 64,
        12: 174,
        4: $V1,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $VS,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }), o([34, 56], $Vx1, {
        9: $VW,
        11: $VX,
        15: $VY
      }), {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 175,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, o($Vx, [2, 70], {
        9: $VW,
        11: $VX,
        15: $VY
      }), {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        17: 177,
        18: $V5,
        19: 176,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        47: $Ve,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 178,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        47: [1, 179],
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, o($VU, [2, 83]), o($VU, [2, 114]), {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 180,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        4: $Vg1,
        5: 129,
        6: 182,
        7: $Vh1,
        10: 181,
        18: [1, 183],
        23: [1, 184],
        25: $Vk1,
        43: 128
      }, o($Vy1, $VQ, {
        3: 12,
        54: 13,
        79: 22,
        5: 32,
        6: 33,
        44: 63,
        19: 64,
        12: 185,
        4: $V1,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $VS,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }), o($Vc1, [2, 9]), {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 186,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, o($VU, [2, 85]), o($VU, [2, 82], {
        9: $VW,
        11: $VX,
        15: $VY
      }), {
        3: 187,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        23: $V6,
        25: $V7,
        39: $Vb,
        40: $VT
      }, {
        3: 188,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        23: $V6,
        25: $V7,
        39: $Vb,
        40: $VT,
        48: [1, 189]
      }, o($Vz1, [2, 92], {
        35: $VA,
        64: $VG,
        68: $VK
      }), {
        3: 173,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 190,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        47: [1, 191],
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, o($VA1, $VQ, {
        3: 12,
        54: 13,
        79: 22,
        5: 32,
        6: 33,
        44: 63,
        19: 64,
        12: 192,
        4: $V1,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $VS,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }), {
        3: 193,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        23: $V6,
        25: $V7,
        39: $Vb,
        40: $VT,
        48: [1, 194]
      }, o($Vz1, [2, 93], {
        35: $VA,
        64: $VG,
        68: $VK
      }), {
        3: 173,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 195,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        3: 196,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        23: $V6,
        25: $V7,
        39: $Vb,
        40: $VT,
        48: [1, 197]
      }, o($Vz1, [2, 94], {
        35: $VA,
        64: $VG,
        68: $VK
      }), {
        3: 173,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 198,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, o($VB1, [2, 101], {
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN
      }), {
        3: 67,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        23: $V6,
        25: $V7,
        39: $Vb,
        40: $VT
      }, o($Vy1, $VQ, {
        3: 12,
        54: 13,
        79: 22,
        5: 32,
        6: 33,
        44: 63,
        19: 64,
        12: 199,
        4: $V1,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $VS,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }), o($Vy1, $VQ, {
        3: 12,
        54: 13,
        79: 22,
        5: 32,
        6: 33,
        44: 63,
        19: 64,
        12: 200,
        4: $V1,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $VS,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }), {
        17: 201,
        35: $VA,
        47: $Ve,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO
      }, o($VU, $VC1, {
        77: 202,
        89: $VD1
      }), {81: [1, 204]}, o($VB1, [2, 123], {
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN
      }), o($VA1, $VQ, {
        3: 12,
        54: 13,
        79: 22,
        5: 32,
        6: 33,
        44: 63,
        19: 64,
        12: 205,
        4: $V1,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $VS,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }), o($VU, [2, 127]), {
        45: $VE1,
        82: $V71,
        87: 206
      }, o($VF1, [2, 131], {
        82: $VG1,
        88: [1, 208],
        89: [1, 209]
      }), o($VU, [2, 134]), o($VH1, [2, 147], {
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO
      }), {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 105,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        86: 211,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, o($VU, [2, 135], {
        91: [1, 212],
        92: [1, 213]
      }), o($V81, $V91, {
        94: 214,
        9: $VW,
        11: $VX,
        15: $VY,
        96: $Va1
      }), {
        47: $VI1,
        95: 215,
        104: $VJ1
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 217,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, o($VK1, [2, 144], {
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL
      }), o($VU, [2, 145]), o($VA1, $VQ, {
        3: 12,
        54: 13,
        79: 22,
        5: 32,
        6: 33,
        44: 63,
        19: 64,
        12: 218,
        4: $V1,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $VS,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }), o($Vy1, $VQ, {
        3: 12,
        54: 13,
        79: 22,
        5: 32,
        6: 33,
        44: 63,
        19: 64,
        12: 219,
        4: $V1,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $VS,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }), o($Vd1, $Vw1, {
        20: 220,
        79: 222,
        35: $VA,
        36: [1, 221],
        40: $VL1,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO,
        81: $Vp
      }), {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 224,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 225,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, o($VM1, $Vt1, {
        13: 226,
        45: $Vu1
      }), o($Vd1, $VQ, {
        3: 12,
        54: 13,
        79: 22,
        5: 32,
        6: 33,
        44: 63,
        19: 64,
        12: 227,
        4: $V1,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $VS,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }), o($VN1, $Vt1, {
        13: 228,
        45: $VO1
      }), o($VP1, [2, 165]), o([22, 45, 46], $Vf1, {
        99: 121,
        10: 123,
        98: 124,
        43: 128,
        5: 129,
        41: 230,
        4: $Vg1,
        7: $Vh1,
        8: $Vi1,
        18: $VQ1,
        23: $Vj1,
        25: $Vk1,
        47: $Vl1,
        48: $Vm1,
        52: $Vn1,
        58: $Vo1
      }), o($VR1, [2, 149], {
        9: [1, 233],
        100: [1, 232]
      }), o($VP1, [2, 157], {
        56: [1, 235],
        62: [1, 234]
      }), {
        4: $Vg1,
        5: 129,
        7: $Vh1,
        8: [1, 237],
        10: 236,
        25: $Vk1,
        43: 128
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 238,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, o($VP1, [2, 163]), o($VS1, [2, 47]), o($VS1, [2, 48]), o($VR1, [2, 150], {9: [1, 239]}), o($Ve1, $Vf1, {
        99: 121,
        10: 123,
        98: 124,
        43: 128,
        5: 129,
        41: 240,
        4: $Vg1,
        7: $Vh1,
        8: $Vi1,
        18: $VQ1,
        23: $Vj1,
        25: $Vk1,
        47: $Vl1,
        48: $Vm1,
        52: $Vn1,
        58: $Vo1
      }), o($VS1, [2, 49]), o($VS1, [2, 50]), o($Vp1, $V0, {
        49: 3,
        17: 4,
        50: 5,
        19: 7,
        3: 12,
        54: 13,
        79: 22,
        5: 32,
        6: 33,
        101: 144,
        4: $V1,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        23: $V6,
        25: $V7,
        31: $V8,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        47: $Ve,
        48: $Vf,
        52: $Vg,
        53: $Vh,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }), {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 242,
        23: $V6,
        25: $V7,
        27: [1, 241],
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, o($Vp1, $Vz, {
        17: 46,
        26: [1, 243],
        28: [1, 244],
        35: [1, 245],
        47: $Ve,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO
      }), {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 247,
        23: $V6,
        25: $V7,
        27: [1, 246],
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        11: [1, 249],
        27: [1, 248]
      }, {27: [1, 250]}, o($VP, $VQ, {
        3: 12,
        54: 13,
        79: 22,
        5: 32,
        6: 33,
        44: 63,
        19: 64,
        12: 251,
        4: $V1,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $VS,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }), {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 83,
        23: $V6,
        25: $V7,
        27: [1, 252],
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        47: $V31,
        48: $V41,
        54: 13,
        56: $V51,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        3: 80,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        23: $V6,
        25: $V7,
        27: [1, 253],
        39: $Vb,
        40: $VT,
        48: $V21
      }, {
        3: 254,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        23: $V6,
        25: $V7,
        39: $Vb,
        40: $VT
      }, {27: [1, 255]}, {
        17: 256,
        35: $VA,
        47: $Ve,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO
      }, {
        17: 257,
        35: $VA,
        37: $VT1,
        47: $Ve,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO,
        82: $VU1
      }, o([21, 22, 24, 35, 37, 40, 46, 47, 57, 58, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 78, 81, 82], $VV, {
        9: $VW,
        11: $VX,
        15: $VY,
        34: $VZ,
        55: $V_,
        56: $V$,
        72: $V01,
        96: $V11,
        102: [1, 260]
      }), o([9, 11, 15, 21, 22, 24, 34, 35, 37, 40, 46, 47, 55, 56, 57, 58, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 78, 81, 82, 96, 102], $Vb1, {
        38: [1, 263],
        45: [1, 262],
        103: [1, 261]
      }), {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 264,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, o($VV1, [2, 198], {
        35: $VA,
        45: [1, 266],
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO,
        82: [1, 265]
      }), o($Vx, [2, 63]), o($Vt, [2, 172], {46: $Vw}), o([1, 9, 11, 14, 15, 21, 22, 24, 26, 27, 28, 32, 34, 35, 36, 37, 40, 45, 46, 47, 55, 56, 57, 58, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 78, 81, 82, 88, 89, 91, 92, 96, 102, 103, 104], [2, 71]), {
        9: $VW,
        11: $VX,
        15: $VY,
        35: [1, 267]
      }, o($VW1, [2, 80], {
        35: $VA,
        58: $VC,
        63: $VF,
        64: $VG,
        68: $VK
      }), o($VA1, $VQ, {
        3: 12,
        54: 13,
        79: 22,
        5: 32,
        6: 33,
        44: 63,
        19: 64,
        12: 268,
        4: $V1,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $VS,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }), o([1, 14, 21, 22, 24, 26, 27, 28, 32, 36, 37, 40, 45, 46, 47, 57, 58, 61, 62, 65, 66, 67, 69, 70, 71, 78, 81, 82, 104], [2, 102], {
        35: $VA,
        63: $VF,
        64: $VG,
        68: $VK
      }), o($VX1, [2, 103], {
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        63: $VF,
        64: $VG,
        65: $VH,
        67: $VJ,
        68: $VK,
        69: $VL
      }), o($VK1, [2, 104], {
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL
      }), o($Vz1, [2, 105], {
        35: $VA,
        64: $VG,
        68: $VK
      }), o($Vz1, [2, 106], {
        35: $VA,
        64: $VG,
        68: $VK
      }), o($VW1, [2, 107], {
        35: $VA,
        58: $VC,
        63: $VF,
        64: $VG,
        68: $VK
      }), o($VX1, [2, 108], {
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        63: $VF,
        64: $VG,
        65: $VH,
        67: $VJ,
        68: $VK,
        69: $VL
      }), o($VY1, [2, 109], {
        35: $VA,
        57: $VB,
        58: $VC,
        63: $VF,
        64: $VG,
        65: $VH,
        67: $VJ,
        68: $VK
      }), o([1, 14, 21, 22, 24, 26, 27, 28, 32, 36, 37, 40, 45, 46, 47, 57, 58, 61, 62, 63, 64, 65, 66, 67, 69, 70, 71, 78, 81, 82, 104], [2, 110], {
        35: $VA,
        68: $VK
      }), o($VY1, [2, 111], {
        35: $VA,
        57: $VB,
        58: $VC,
        63: $VF,
        64: $VG,
        65: $VH,
        67: $VJ,
        68: $VK
      }), o($VK1, [2, 112], {
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL
      }), o($VB1, [2, 113], {
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN
      }), o($VB1, [2, 119], {
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN
      }), {
        32: [1, 269],
        46: $VZ1,
        47: $V_1
      }, o([14, 21, 22, 32, 46, 47], $V$1, {
        3: 12,
        54: 13,
        79: 22,
        5: 32,
        6: 33,
        19: 64,
        44: 272,
        4: $V1,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $VS,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }), o($Vv1, [2, 57], {
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO
      }), o($VU, $VV, {
        9: $VW,
        11: $VX,
        15: $VY,
        34: $Vx1,
        56: $Vx1,
        55: $V_,
        72: $V01,
        96: $V11
      }), o($Vs1, $Vt1, {
        13: 273,
        45: $Vu1
      }), {
        17: 257,
        35: $VA,
        47: $Ve,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO
      }, o($VW1, [2, 73], {
        35: $VA,
        58: $VC,
        63: $VF,
        64: $VG,
        68: $VK
      }), o($VU, [2, 74]), o($VB1, [2, 77], {
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN
      }), o($VA1, $VQ, {
        3: 12,
        54: 13,
        79: 22,
        5: 32,
        6: 33,
        44: 63,
        19: 64,
        12: 274,
        4: $V1,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $VS,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }), o($VK1, [2, 143], {
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL
      }), o($Vc1, [2, 6]), o($Vc1, [2, 7]), o($Vd1, $VQ, {
        3: 12,
        54: 13,
        79: 22,
        5: 32,
        6: 33,
        44: 63,
        12: 118,
        19: 275,
        4: $V1,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        36: [1, 276],
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $VS,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }), o($Ve1, $Vf1, {
        41: 120,
        99: 121,
        10: 123,
        98: 124,
        43: 128,
        5: 129,
        4: $Vg1,
        7: $Vh1,
        8: $Vi1,
        18: $VQ1,
        23: $Vj1,
        25: $Vk1,
        47: $Vl1,
        48: $Vm1,
        52: $Vn1,
        58: $Vo1
      }), o($V02, $Vt1, {
        13: 277,
        45: $Vu1
      }), o($VB1, [2, 78], {
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN
      }), o($VU, [2, 84], {
        9: $VW,
        11: $VX,
        15: $VY
      }), o($VU, [2, 86], {
        9: $VW,
        11: $VX,
        15: $VY
      }), {
        3: 278,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        23: $V6,
        25: $V7,
        39: $Vb,
        40: $VT
      }, o($Vz1, [2, 95], {
        35: $VA,
        64: $VG,
        68: $VK
      }), o($VA1, $VQ, {
        3: 12,
        54: 13,
        79: 22,
        5: 32,
        6: 33,
        44: 63,
        19: 64,
        12: 279,
        4: $V1,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $VS,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }), o($V12, $Vt1, {
        13: 280,
        45: $Vu1
      }), o($VU, [2, 87], {
        9: $VW,
        11: $VX,
        15: $VY
      }), {
        3: 281,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        23: $V6,
        25: $V7,
        39: $Vb,
        40: $VT
      }, o($Vz1, [2, 96], {
        35: $VA,
        64: $VG,
        68: $VK
      }), o($VU, [2, 88], {
        9: $VW,
        11: $VX,
        15: $VY
      }), {
        3: 282,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        23: $V6,
        25: $V7,
        39: $Vb,
        40: $VT
      }, o($Vz1, [2, 97], {
        35: $VA,
        64: $VG,
        68: $VK
      }), o($V02, $Vt1, {
        13: 283,
        45: $Vu1
      }), o($V02, $Vt1, {
        13: 284,
        45: $Vu1
      }), o($VU, $VC1, {
        77: 285,
        89: $VD1
      }), o($VU, [2, 120]), {
        17: 286,
        47: $Ve,
        76: [1, 287]
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 288,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, o($V12, $Vt1, {
        13: 289,
        45: $Vu1
      }), o($VF1, [2, 128], {
        82: $VG1,
        88: [1, 290],
        89: [1, 291]
      }), {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 292,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        17: 293,
        47: $Ve
      }, {
        17: 294,
        47: $Ve
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 105,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        86: 295,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        17: 296,
        45: $VE1,
        47: $Ve
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        17: 297,
        18: $V5,
        19: 64,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        44: 298,
        47: $Ve,
        48: $VS,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        17: 299,
        47: $Ve
      }, {
        47: $VI1,
        95: 300,
        104: $VJ1
      }, {
        17: 301,
        47: $Ve
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 105,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        86: 302,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, o($V81, [2, 208], {
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO
      }), o($V12, $Vt1, {
        13: 303,
        45: $Vu1
      }), o($V02, $Vt1, {
        13: 304,
        45: $Vu1
      }), {
        21: [1, 305],
        22: [1, 306],
        40: $VL1,
        46: $V22,
        47: $V32,
        79: 307,
        81: $Vp
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 310,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, o($VV1, [2, 202]), {
        3: 147,
        4: $Vq1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 311,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        38: $Vr1,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        35: $VA,
        36: [1, 312],
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO
      }, {
        21: [1, 313],
        35: $VA,
        37: [1, 314],
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO
      }, {
        21: [1, 315],
        46: $VZ1,
        47: $V_1
      }, o($VM1, $Vt1, {
        13: 316,
        45: $Vu1
      }), {
        24: [1, 317],
        46: $V42
      }, o([22, 24, 46], $V$1, {
        10: 123,
        98: 124,
        43: 128,
        5: 129,
        99: 319,
        4: $Vg1,
        7: $Vh1,
        8: $Vi1,
        18: $VQ1,
        23: $Vj1,
        25: $Vk1,
        48: $Vm1,
        52: $Vn1,
        58: $Vo1
      }), o($Vy, $Vt1, {
        13: 320,
        45: $VO1
      }), o($Vd1, $VQ, {
        3: 12,
        54: 13,
        79: 22,
        5: 32,
        6: 33,
        44: 63,
        19: 64,
        12: 321,
        4: $V1,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $VS,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }), {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 322,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        47: [1, 323],
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        4: $Vg1,
        7: $Vh1,
        43: 324
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 325,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 326,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, o($VP1, [2, 160]), o($VP1, [2, 161]), o($VP1, [2, 162], {
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO
      }), {
        4: $Vg1,
        7: $Vh1,
        43: 327
      }, o($VN1, $Vt1, {
        13: 328,
        45: $VO1
      }), o($Vc1, [2, 14]), {
        27: [1, 329],
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO
      }, {27: [1, 330]}, {27: [1, 331]}, {
        3: 332,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        23: $V6,
        25: $V7,
        39: $Vb,
        40: $VT
      }, o($Vc1, [2, 17]), {
        27: [1, 333],
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO
      }, o($Vc1, [2, 20]), o($Vy1, $VQ, {
        3: 12,
        54: 13,
        79: 22,
        5: 32,
        6: 33,
        44: 63,
        19: 64,
        12: 334,
        4: $V1,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $VS,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }), o($Vc1, [2, 22]), o($Vs1, $Vt1, {
        13: 335,
        45: $Vu1
      }), o($Vc1, [2, 24]), o($Vc1, [2, 25]), {
        9: $VW,
        11: $VX,
        15: $VY,
        35: [1, 336]
      }, o($VS1, [2, 169]), o($Vc1, [2, 41]), o($Vc1, [2, 42]), {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 337,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 338,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 339,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 340,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        3: 341,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        23: $V6,
        25: $V7,
        39: $Vb,
        40: $VT
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 342,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        35: $VA,
        36: [1, 343],
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 344,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 345,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 346,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, o($V12, $Vt1, {
        13: 347,
        45: $Vu1
      }), {
        51: $V52,
        73: $V62
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 64,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        44: 350,
        48: $VS,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, o($VA1, $VQ, {
        3: 12,
        54: 13,
        79: 22,
        5: 32,
        6: 33,
        44: 63,
        19: 64,
        12: 351,
        4: $V1,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $VS,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }), o($Vv1, [2, 53]), {
        32: [1, 352],
        46: $VZ1,
        47: $V_1
      }, o($V12, $Vt1, {
        13: 353,
        45: $Vu1
      }), o($Vd1, $Vw1, {
        35: $VA,
        36: [1, 354],
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO
      }), {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 355,
        21: [1, 356],
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        14: [1, 357],
        46: $VZ1,
        47: $V_1
      }, o($VU, [2, 89], {
        9: $VW,
        11: $VX,
        15: $VY
      }), o($V12, $Vt1, {
        13: 358,
        45: $Vu1
      }), {
        22: [1, 359],
        46: $VZ1,
        47: $V_1
      }, o($VU, [2, 90], {
        9: $VW,
        11: $VX,
        15: $VY
      }), o($VU, [2, 91], {
        9: $VW,
        11: $VX,
        15: $VY
      }), {
        14: [1, 360],
        46: $VZ1,
        47: $V_1
      }, {
        14: [1, 361],
        46: $VZ1,
        47: $V_1
      }, o($VU, [2, 118]), o($VU, [2, 174]), {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 362,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, o([1, 14, 21, 22, 24, 26, 27, 28, 32, 36, 37, 40, 45, 46, 47, 70, 71, 78, 81, 104], [2, 121], {
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        82: [1, 363]
      }), {
        22: [1, 364],
        46: $VZ1,
        47: $V_1
      }, {
        17: 365,
        47: $Ve
      }, {
        17: 366,
        47: $Ve
      }, o($VH1, [2, 148], {
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO
      }), o($VU, [2, 132]), o($VU, [2, 133]), {
        17: 367,
        45: $VE1,
        47: $Ve
      }, o($V72, [2, 206]), o($VU, [2, 136], {92: [1, 368]}), {
        17: 369,
        47: $Ve
      }, o($VU, [2, 140]), {
        17: 370,
        47: $Ve
      }, o($VU, [2, 142]), {
        45: $VE1,
        47: [2, 210]
      }, {
        22: [1, 371],
        46: $VZ1,
        47: $V_1
      }, {
        14: [1, 372],
        46: $VZ1,
        47: $V_1
      }, o($Vc1, [2, 11]), {21: [1, 373]}, o($VV1, [2, 203]), {
        40: $VL1,
        79: 374,
        81: $Vp
      }, {
        40: $VL1,
        79: 375,
        81: $Vp
      }, {
        21: [1, 376],
        35: $VA,
        37: [1, 377],
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO
      }, o($VV1, [2, 180], {
        35: $VA,
        37: $VT1,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO,
        82: $VU1
      }), {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 378,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, o($Vc1, [2, 33]), {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 379,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, o($Vc1, [2, 43], {42: [1, 380]}), {
        21: [1, 381],
        46: $VZ1,
        47: $V_1
      }, o($Vc1, [2, 44], {42: [1, 382]}), {
        4: $Vg1,
        5: 129,
        7: $Vh1,
        8: $Vi1,
        10: 123,
        18: $VQ1,
        23: $Vj1,
        25: $Vk1,
        43: 128,
        48: $Vm1,
        52: $Vn1,
        58: $Vo1,
        98: 124,
        99: 383
      }, o($VP1, [2, 166]), {
        22: [1, 384],
        46: $V42
      }, o($VM1, $Vt1, {
        13: 385,
        45: $Vu1
      }), o($VP1, [2, 155], {
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO
      }), o($VA1, $VQ, {
        3: 12,
        54: 13,
        79: 22,
        5: 32,
        6: 33,
        44: 63,
        19: 64,
        12: 386,
        4: $V1,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $VS,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }), o($VR1, [2, 151]), o($VP1, [2, 158], {
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO
      }), o($VP1, [2, 159], {
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO
      }), o($VR1, [2, 152]), {
        24: [1, 387],
        46: $V42
      }, o($Vc1, [2, 15]), o($Vc1, [2, 16]), o($Vc1, [2, 19]), {
        9: $VW,
        11: $VX,
        15: $VY,
        35: [1, 388]
      }, o($Vc1, [2, 18]), o($V02, $Vt1, {
        13: 389,
        45: $Vu1
      }), {
        32: [1, 390],
        46: $VZ1,
        47: $V_1
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 392,
        23: $V6,
        25: $V7,
        27: [1, 391],
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, o($VV1, [2, 181], {
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO
      }), o($VV1, [2, 182], {
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO,
        82: [1, 393]
      }), o($VV1, [2, 176], {
        35: $VA,
        37: [1, 395],
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO,
        82: [1, 394]
      }), o($VV1, [2, 184], {
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO,
        82: [1, 396]
      }), {
        9: $VW,
        11: $VX,
        15: $VY,
        103: [1, 397]
      }, {
        35: $VA,
        36: [1, 398],
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 399,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, o($VV1, [2, 199], {
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO
      }), o($VV1, [2, 200], {
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO,
        82: [1, 400]
      }), o($VU, [2, 75]), {
        22: [1, 401],
        46: $VZ1,
        47: $V_1
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 402,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        17: 403,
        47: $Ve
      }, o($Vv1, [2, 54]), o($V12, $Vt1, {
        13: 404,
        45: $Vu1
      }), {73: $V62}, {
        22: [1, 405],
        46: $VZ1,
        47: $V_1
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 406,
        21: [1, 407],
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        21: [1, 409],
        35: $VA,
        37: [1, 408],
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO
      }, o($Vc1, [2, 40]), o($Vc1, [2, 8]), {
        22: [1, 410],
        46: $VZ1,
        47: $V_1
      }, o($VU, [2, 99]), {
        17: 411,
        47: $Ve
      }, {
        17: 412,
        47: $Ve
      }, {
        17: 413,
        35: $VA,
        47: $Ve,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 414,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, o($VU, [2, 124]), o($VU, [2, 129]), o($VU, [2, 130]), o($V72, [2, 207]), {
        17: 415,
        47: $Ve
      }, o($VU, [2, 138], {92: [1, 416]}), o($VU, [2, 141]), o($VU, [2, 146]), {
        17: 417,
        47: $Ve
      }, o($Vc1, [2, 12]), o($VV1, [2, 204]), o($VV1, [2, 205]), o($Vc1, [2, 29]), {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 418,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        21: [1, 419],
        35: $VA,
        37: [1, 420],
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO
      }, {
        21: [1, 421],
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO
      }, o($Vc1, [2, 45]), {
        20: 422,
        40: $VL1,
        42: $V82,
        79: 222,
        81: $Vp
      }, o($Vc1, [2, 46]), o($VP1, [2, 167]), o($VP1, [2, 168]), {
        21: [1, 424],
        46: $VZ1,
        47: $V_1
      }, o($V12, $Vt1, {
        13: 425,
        45: $Vu1
      }), {42: [1, 426]}, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 346,
        23: $V6,
        25: $V7,
        27: [1, 427],
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        14: [1, 428],
        46: $VZ1,
        47: $V_1
      }, {
        30: [1, 429],
        51: $V52,
        73: $V62
      }, o($Vc1, [2, 26]), {
        27: [1, 430],
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 431,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 432,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 433,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 434,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 435,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 436,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, o($VV1, [2, 189], {
        35: $VA,
        37: [1, 438],
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO,
        82: [1, 437]
      }), {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 439,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, o($VU, [2, 81]), o($Vx, [2, 67], {
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO
      }), o($VU, [2, 115]), {
        22: [1, 440],
        46: $VZ1,
        47: $V_1
      }, o($VU, [2, 79]), {
        21: [1, 442],
        35: $VA,
        37: [1, 441],
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO
      }, o($Vc1, [2, 38]), {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 443,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, o($Vc1, [2, 39]), o($VU, [2, 98]), o($VU, [2, 116]), o($VU, [2, 117]), o($VU, $VC1, {
        77: 444,
        89: $VD1
      }), o($VK1, [2, 122], {
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL
      }), o($VU, [2, 137]), {
        17: 445,
        47: $Ve
      }, o($Vc1, [2, 10]), {
        21: [1, 446],
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO
      }, o($Vc1, [2, 31]), {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 447,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, o($Vc1, [2, 34]), {
        24: [1, 448],
        40: $VL1,
        46: $V22,
        47: $V32,
        79: 307,
        81: $Vp
      }, o($VR1, [2, 154]), {42: $V82}, {
        22: [1, 449],
        46: $VZ1,
        47: $V_1
      }, o($VR1, [2, 153]), o($Vc1, [2, 27]), {27: [1, 450]}, {27: [1, 451]}, o($Vc1, [2, 28]), o($VV1, [2, 183], {
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO
      }), o($VV1, [2, 177], {
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO
      }), o($VV1, [2, 178], {
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO,
        82: [1, 452]
      }), o($VV1, [2, 185], {
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO
      }), o($VV1, [2, 186], {
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO,
        82: [1, 453]
      }), o($VV1, [2, 188], {
        35: $VA,
        37: [1, 455],
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO,
        82: [1, 454]
      }), {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 456,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 457,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, o($VV1, [2, 201], {
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO
      }), o($Vv1, [2, 55]), {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 458,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, o($Vc1, [2, 37]), {
        21: [1, 459],
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO
      }, o($VU, [2, 175]), o($VU, [2, 139]), o($Vc1, [2, 30]), {
        21: [1, 460],
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO
      }, o($Vc1, [2, 13]), o($VP1, [2, 156]), o($Vc1, [2, 21]), o($Vc1, [2, 23]), {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 461,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 462,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 463,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 464,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, o($VV1, [2, 191], {
        35: $VA,
        37: [1, 465],
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO
      }), o($VV1, [2, 193], {
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO,
        82: [1, 466]
      }), {
        21: [1, 467],
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO
      }, o($Vc1, [2, 36]), o($Vc1, [2, 32]), o($VV1, [2, 179], {
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO
      }), o($VV1, [2, 187], {
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO
      }), o($VV1, [2, 190], {
        35: $VA,
        37: [1, 468],
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO
      }), o($VV1, [2, 192], {
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO,
        82: [1, 469]
      }), {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 470,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 471,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, o($Vc1, [2, 35]), {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 472,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, {
        3: 12,
        4: $V1,
        5: 32,
        6: 33,
        7: $V2,
        8: $V3,
        16: $V4,
        18: $V5,
        19: 473,
        23: $V6,
        25: $V7,
        31: $VR,
        33: $V9,
        34: $Va,
        39: $Vb,
        40: $Vc,
        42: $Vd,
        48: $V61,
        54: 13,
        58: $Vi,
        59: $Vj,
        60: $Vk,
        74: $Vl,
        75: $Vm,
        76: $Vn,
        79: 22,
        80: $Vo,
        81: $Vp,
        83: $Vq,
        84: $Vr,
        85: $Vs,
        90: $Vt,
        93: $Vu,
        97: $Vv
      }, o($VV1, [2, 197], {
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO
      }), o($VV1, [2, 195], {
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO
      }), o($VV1, [2, 196], {
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO
      }), o($VV1, [2, 194], {
        35: $VA,
        57: $VB,
        58: $VC,
        61: $VD,
        62: $VE,
        63: $VF,
        64: $VG,
        65: $VH,
        66: $VI,
        67: $VJ,
        68: $VK,
        69: $VL,
        70: $VM,
        71: $VN,
        78: $VO
      })],
      defaultActions: {2: [2, 212]},
      parseError: function parseError(str, hash) {
        if (hash.recoverable) {
          this.trace(str);
        } else {
          function _parseError(msg, hash) {
            this.message = msg;
            this.hash = hash;
          }
          _parseError.prototype = Error;
          throw new _parseError(str, hash);
        }
      },
      parse: function parse(input) {
        var self = this,
            stack = [0],
            tstack = [],
            vstack = [null],
            lstack = [],
            table = this.table,
            yytext = '',
            yylineno = 0,
            yyleng = 0,
            recovering = 0,
            TERROR = 2,
            EOF = 1;
        var args = lstack.slice.call(arguments, 1);
        var lexer = Object.create(this.lexer);
        var sharedState = {yy: {}};
        for (var k in this.yy) {
          if (Object.prototype.hasOwnProperty.call(this.yy, k)) {
            sharedState.yy[k] = this.yy[k];
          }
        }
        lexer.setInput(input, sharedState.yy);
        sharedState.yy.lexer = lexer;
        sharedState.yy.parser = this;
        if (typeof lexer.yylloc == 'undefined') {
          lexer.yylloc = {};
        }
        var yyloc = lexer.yylloc;
        lstack.push(yyloc);
        var ranges = lexer.options && lexer.options.ranges;
        if (typeof sharedState.yy.parseError === 'function') {
          this.parseError = sharedState.yy.parseError;
        } else {
          this.parseError = Object.getPrototypeOf(this).parseError;
        }
        function popStack(n) {
          stack.length = stack.length - 2 * n;
          vstack.length = vstack.length - n;
          lstack.length = lstack.length - n;
        }
        _token_stack: var lex = function() {
          var token;
          token = lexer.lex() || EOF;
          if (typeof token !== 'number') {
            token = self.symbols_[token] || token;
          }
          return token;
        };
        var symbol,
            preErrorSymbol,
            state,
            action,
            a,
            r,
            yyval = {},
            p,
            len,
            newState,
            expected;
        while (true) {
          state = stack[stack.length - 1];
          if (this.defaultActions[state]) {
            action = this.defaultActions[state];
          } else {
            if (symbol === null || typeof symbol == 'undefined') {
              symbol = lex();
            }
            action = table[state] && table[state][symbol];
          }
          if (typeof action === 'undefined' || !action.length || !action[0]) {
            var errStr = '';
            expected = [];
            for (p in table[state]) {
              if (this.terminals_[p] && p > TERROR) {
                expected.push('\'' + this.terminals_[p] + '\'');
              }
            }
            if (lexer.showPosition) {
              errStr = 'Parse error on line ' + (yylineno + 1) + ':\n' + lexer.showPosition() + '\nExpecting ' + expected.join(', ') + ', got \'' + (this.terminals_[symbol] || symbol) + '\'';
            } else {
              errStr = 'Parse error on line ' + (yylineno + 1) + ': Unexpected ' + (symbol == EOF ? 'end of input' : '\'' + (this.terminals_[symbol] || symbol) + '\'');
            }
            this.parseError(errStr, {
              text: lexer.match,
              token: this.terminals_[symbol] || symbol,
              line: lexer.yylineno,
              loc: yyloc,
              expected: expected
            });
          }
          if (action[0] instanceof Array && action.length > 1) {
            throw new Error('Parse Error: multiple actions possible at state: ' + state + ', token: ' + symbol);
          }
          switch (action[0]) {
            case 1:
              stack.push(symbol);
              vstack.push(lexer.yytext);
              lstack.push(lexer.yylloc);
              stack.push(action[1]);
              symbol = null;
              if (!preErrorSymbol) {
                yyleng = lexer.yyleng;
                yytext = lexer.yytext;
                yylineno = lexer.yylineno;
                yyloc = lexer.yylloc;
                if (recovering > 0) {
                  recovering--;
                }
              } else {
                symbol = preErrorSymbol;
                preErrorSymbol = null;
              }
              break;
            case 2:
              len = this.productions_[action[1]][1];
              yyval.$ = vstack[vstack.length - len];
              yyval._$ = {
                first_line: lstack[lstack.length - (len || 1)].first_line,
                last_line: lstack[lstack.length - 1].last_line,
                first_column: lstack[lstack.length - (len || 1)].first_column,
                last_column: lstack[lstack.length - 1].last_column
              };
              if (ranges) {
                yyval._$.range = [lstack[lstack.length - (len || 1)].range[0], lstack[lstack.length - 1].range[1]];
              }
              r = this.performAction.apply(yyval, [yytext, yyleng, yylineno, sharedState.yy, action[1], vstack, lstack].concat(args));
              if (typeof r !== 'undefined') {
                return r;
              }
              if (len) {
                stack = stack.slice(0, -1 * len * 2);
                vstack = vstack.slice(0, -1 * len);
                lstack = lstack.slice(0, -1 * len);
              }
              stack.push(this.productions_[action[1]][0]);
              vstack.push(yyval.$);
              lstack.push(yyval._$);
              newState = table[stack[stack.length - 2]][stack[stack.length - 1]];
              stack.push(newState);
              break;
            case 3:
              return true;
          }
        }
        return true;
      }
    };
    function Parser() {
      this.yy = {};
    }
    Parser.prototype = parser;
    parser.Parser = Parser;
    return new Parser;
  })();
  if (typeof $__require !== 'undefined' && typeof exports !== 'undefined') {
    exports.parser = parser;
    exports.Parser = parser.Parser;
    exports.parse = function() {
      return parser.parse.apply(parser, arguments);
    };
    exports.main = function commonjsMain(args) {
      if (!args[1]) {
        console.log('Usage: ' + args[0] + ' FILE');
        process.exit(1);
      }
      var source = $__require('4').readFileSync($__require('5').normalize(args[1]), "utf8");
      return exports.parser.parse(source);
    };
    if (typeof module !== 'undefined' && $__require.main === module) {
      exports.main(process.argv.slice(1));
    }
  }
  return module.exports;
});

$__System.registerDynamic("6", ["5"], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  var path,
      stripString,
      nameFromPath;
  path = $__require('5');
  stripString = function(val) {
    var that;
    if (that = /^['"](.*)['"]$/.exec(val.trim())) {
      return that[1];
    } else {
      return val;
    }
  };
  nameFromPath = function(modulePath) {
    return path.basename(stripString(modulePath)).split('.')[0].replace(/-[a-z]/ig, function(it) {
      return it.charAt(1).toUpperCase();
    });
  };
  module.exports = {
    nameFromPath: nameFromPath,
    stripString: stripString
  };
  return module.exports;
});

$__System.registerDynamic("7", ["8", "6", "9"], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  var fold,
      ref$,
      nameFromPath,
      stripString,
      SourceNode,
      SourceMapGenerator,
      sn,
      snEmpty,
      snSafe,
      snRemoveLeft,
      snAutofill,
      Node,
      Negatable,
      Block,
      Atom,
      Literal,
      Var,
      Key,
      Index,
      Slice,
      Chain,
      Call,
      List,
      Obj,
      Prop,
      Arr,
      Yield,
      Unary,
      Binary,
      Assign,
      Import,
      In,
      Existence,
      Fun,
      Class,
      Super,
      Parens,
      Splat,
      Jump,
      Throw,
      Return,
      While,
      For,
      StepSlice,
      Try,
      Switch,
      Case,
      If,
      Label,
      Cascade,
      JS,
      Require,
      Util,
      Vars,
      CopyL,
      DECLS,
      UTILS,
      LEVEL_TOP,
      LEVEL_PAREN,
      LEVEL_LIST,
      LEVEL_COND,
      LEVEL_OP,
      LEVEL_CALL,
      PREC,
      TAB,
      ID,
      SIMPLENUM,
      slice$ = [].slice,
      toString$ = {}.toString;
  fold = $__require('8').fold;
  ref$ = $__require('6'), nameFromPath = ref$.nameFromPath, stripString = ref$.stripString;
  ref$ = $__require('9'), SourceNode = ref$.SourceNode, SourceMapGenerator = ref$.SourceMapGenerator;
  sn = function(node) {
    var parts,
        res$,
        i$,
        to$,
        result,
        e;
    node == null && (node = {});
    res$ = [];
    for (i$ = 1, to$ = arguments.length; i$ < to$; ++i$) {
      res$.push(arguments[i$]);
    }
    parts = res$;
    try {
      result = new SourceNode(node.line, node.column, null, parts);
      result.displayName = node.constructor.displayName;
      return result;
    } catch (e$) {
      e = e$;
      console.dir(parts);
      throw e;
    }
  };
  snEmpty = function(node) {
    var i$,
        ref$,
        len$,
        child;
    if (node instanceof SourceNode) {
      for (i$ = 0, len$ = (ref$ = node.children).length; i$ < len$; ++i$) {
        child = ref$[i$];
        if (!snEmpty(child)) {
          return false;
        }
      }
      return true;
    } else {
      return !node;
    }
  };
  snSafe = function(code) {
    if (code instanceof SourceNode) {
      return code;
    } else {
      return code.toString();
    }
  };
  snRemoveLeft = function(node, count) {
    var i$,
        to$,
        i,
        child;
    for (i$ = 0, to$ = node.children.length; i$ < to$; ++i$) {
      i = i$;
      child = node.children[i];
      if (child instanceof SourceNode) {
        count = snRemoveLeft(child, count);
      } else {
        child = child.toString();
        node.children[i] = child.slice(count);
        count -= child.length;
      }
      if (count <= 0) {
        return 0;
      }
    }
    return count;
  };
  snAutofill = function(node, parents) {
    var i$,
        len$,
        p,
        ref$,
        child;
    parents == null && (parents = []);
    if (node instanceof SourceNode) {
      if (node.line) {
        for (i$ = 0, len$ = parents.length; i$ < len$; ++i$) {
          p = parents[i$];
          p.line = node.line;
          p.column = node.column;
        }
        parents.length = 0;
      } else {
        parents.push(node);
      }
      for (i$ = 0, len$ = (ref$ = node.children).length; i$ < len$; ++i$) {
        child = ref$[i$];
        snAutofill(child, parents);
      }
    }
    return node;
  };
  SourceNode.prototype.replace = function() {
    var args,
        res$,
        i$,
        to$;
    res$ = [];
    for (i$ = 0, to$ = arguments.length; i$ < to$; ++i$) {
      res$.push(arguments[i$]);
    }
    args = res$;
    return new SourceNode(this.line, this.column, this.source, (function() {
      var i$,
          x$,
          ref$,
          len$,
          results$ = [];
      for (i$ = 0, len$ = (ref$ = this.children).length; i$ < len$; ++i$) {
        x$ = ref$[i$];
        results$.push(x$.replace.apply(x$, args));
      }
      return results$;
    }.call(this)), this.name);
  };
  SourceNode.prototype.setFile = function(filename) {
    var i$,
        ref$,
        len$,
        child,
        results$ = [];
    this.source = filename;
    for (i$ = 0, len$ = (ref$ = this.children).length; i$ < len$; ++i$) {
      child = ref$[i$];
      if (child instanceof SourceNode) {
        results$.push(child.setFile(filename));
      }
    }
    return results$;
  };
  SourceNode.prototype.toStringWithSourceMap = function() {
    var args,
        res$,
        i$,
        to$,
        gen,
        genLine,
        genColumn,
        stack,
        code,
        debugOutput,
        debugIndent,
        debugIndentStr,
        genForNode;
    res$ = [];
    for (i$ = 0, to$ = arguments.length; i$ < to$; ++i$) {
      res$.push(arguments[i$]);
    }
    args = res$;
    gen = (function(func, args, ctor) {
      ctor.prototype = func.prototype;
      var child = new ctor,
          result = func.apply(child, args),
          t;
      return (t = typeof result) == "object" || t == "function" ? result || child : child;
    })(SourceMapGenerator, args, function() {});
    genLine = 1;
    genColumn = 0;
    stack = [];
    code = '';
    debugOutput = '';
    debugIndent = '';
    debugIndentStr = '  ';
    genForNode = function(node) {
      var valid,
          i$,
          ref$,
          len$,
          child,
          cur,
          to$,
          i,
          c,
          results$ = [];
      if (node instanceof SourceNode) {
        debugOutput += debugIndent + node.displayName;
        valid = node.line && 'column' in node;
        if (valid) {
          stack.push(node);
          debugOutput += '!';
        }
        debugOutput += " " + node.line + ":" + node.column + " " + genLine + ":" + genColumn + "\n";
        debugIndent += debugIndentStr;
        for (i$ = 0, len$ = (ref$ = node.children).length; i$ < len$; ++i$) {
          child = ref$[i$];
          genForNode(child);
        }
        debugIndent = debugIndent.slice(0, debugIndent.length - debugIndentStr.length);
        if (valid) {
          return stack.pop();
        }
      } else {
        debugOutput += debugIndent + "" + JSON.stringify(node) + "\n";
        code += node;
        cur = stack[stack.length - 1];
        if (cur) {
          gen.addMapping({
            source: cur.source,
            original: {
              line: cur.line,
              column: cur.column
            },
            generated: {
              line: genLine,
              column: genColumn
            },
            name: cur.name
          });
        }
        for (i$ = 0, to$ = node.length; i$ < to$; ++i$) {
          i = i$;
          c = node.charAt(i);
          if (c === "\n") {
            genColumn = 0;
            ++genLine;
            if (cur) {
              results$.push(gen.addMapping({
                source: cur.source,
                original: {
                  line: cur.line,
                  column: cur.column
                },
                generated: {
                  line: genLine,
                  column: genColumn
                },
                name: cur.name
              }));
            }
          } else {
            results$.push(++genColumn);
          }
        }
        return results$;
      }
    };
    genForNode(this);
    return {
      code: code,
      map: gen,
      debug: debugOutput
    };
  };
  (Node = function() {
    throw Error('unimplemented');
  }).prototype = {
    compile: function(options, level) {
      var o,
          node,
          code,
          that,
          i$,
          len$,
          tmp;
      o = import$({}, options);
      if (level != null) {
        o.level = level;
      }
      node = this.unfoldSoak(o) || this;
      if (o.level && node.isStatement()) {
        return node.compileClosure(o);
      }
      code = (node.tab = o.indent, node).compileNode(o);
      if (that = node.temps) {
        for (i$ = 0, len$ = that.length; i$ < len$; ++i$) {
          tmp = that[i$];
          o.scope.free(tmp);
        }
      }
      return code;
    },
    compileClosure: function(o) {
      var that,
          fun,
          call,
          hasArgs,
          hasThis,
          out;
      if (that = this.getJump()) {
        that.carp('inconvertible statement');
      }
      fun = Fun([], Block(this));
      call = Call();
      if (o.inGenerator) {
        fun.generator = true;
      }
      this.traverseChildren(function(it) {
        switch (it.value) {
          case 'this':
            hasThis = true;
            break;
          case 'arguments':
            hasArgs = it.value = 'args$';
        }
      });
      if (hasThis) {
        call.args.push(Literal('this'));
        call.method = '.call';
      }
      if (hasArgs) {
        call.args.push(Literal('arguments'));
        fun.params.push(Var('args$'));
      }
      out = Parens(Chain((fun.wrapper = true, fun['void'] = this['void'], fun), [call]), true);
      if (o.inGenerator) {
        out = new Yield('yieldfrom', out);
      }
      return out.compile(o);
    },
    compileBlock: function(o, node) {
      var code;
      if (!snEmpty(code = node != null ? node.compile(o, LEVEL_TOP) : void 8)) {
        return sn(null, "{\n", code, "\n" + this.tab + "}");
      } else {
        return sn(node, '{}');
      }
    },
    compileSpreadOver: function(o, list, transform) {
      var ob,
          them,
          i$,
          len$,
          i,
          node,
          sp,
          lat,
          ref$;
      ob = list instanceof Obj;
      them = list.items;
      for (i$ = 0, len$ = them.length; i$ < len$; ++i$) {
        i = i$;
        node = them[i$];
        if (sp = node instanceof Splat) {
          node = node.it;
        }
        if (ob && !sp) {
          node = node.val;
        }
        node = transform(node);
        if (sp) {
          node = lat = Splat(node);
        }
        if (ob && !sp) {
          them[i].val = node;
        } else {
          them[i] = node;
        }
      }
      if (!lat && (this['void'] || !o.level)) {
        list = (ref$ = Block(ob ? (function() {
          var i$,
              x$,
              ref$,
              len$,
              results$ = [];
          for (i$ = 0, len$ = (ref$ = them).length; i$ < len$; ++i$) {
            x$ = ref$[i$];
            results$.push(x$.val);
          }
          return results$;
        }()) : them), ref$.front = this.front, ref$['void'] = true, ref$);
      }
      return list.compile(o, LEVEL_PAREN);
    },
    cache: function(o, once, level) {
      var ref$,
          sub,
          ref;
      if (!this.isComplex()) {
        return [ref$ = level != null ? this.compile(o, level) : this, ref$];
      }
      sub = Assign(ref = Var(o.scope.temporary()), this);
      if (level != null) {
        sub = sub.compile(o, level);
        if (once) {
          o.scope.free(ref.value);
        }
        return [sub, ref.value];
      }
      if (once) {
        return [sub, (ref.temp = true, ref)];
      } else {
        return [sub, ref, [ref.value]];
      }
    },
    compileLoopReference: function(o, name, ret, safeAccess) {
      var ref$,
          code,
          asn,
          tmp;
      if (this instanceof Var && o.scope.check(this.value) || this instanceof Unary && ((ref$ = this.op) === '+' || ref$ === '-') && (-1 / 0 < (ref$ = +this.it.value) && ref$ < 1 / 0) || this instanceof Literal && !this.isComplex()) {
        code = this.compile(o, LEVEL_PAREN);
        if (safeAccess && !(this instanceof Var)) {
          code = "(" + code + ")";
        }
        return [code, code];
      }
      asn = Assign(Var(tmp = o.scope.temporary(name)), this);
      ret || (asn['void'] = true);
      return [tmp, asn.compile(o, ret ? LEVEL_CALL : LEVEL_PAREN)];
    },
    eachChild: function(fn) {
      var i$,
          ref$,
          len$,
          name,
          child,
          j$,
          len1$,
          i,
          node,
          that;
      for (i$ = 0, len$ = (ref$ = this.children).length; i$ < len$; ++i$) {
        name = ref$[i$];
        if (child = this[name]) {
          if ('length' in child) {
            for (j$ = 0, len1$ = child.length; j$ < len1$; ++j$) {
              i = j$;
              node = child[j$];
              if (that = fn(node, name, i)) {
                return that;
              }
            }
          } else {
            if ((that = fn(child, name)) != null) {
              return that;
            }
          }
        }
      }
    },
    traverseChildren: function(fn, xscope) {
      var this$ = this;
      return this.eachChild(function(node, name, index) {
        var ref$;
        return (ref$ = fn(node, this$, name, index)) != null ? ref$ : node.traverseChildren(fn, xscope);
      });
    },
    anaphorize: function() {
      var base,
          name,
          ref$;
      this.children = this.aTargets;
      if (this.eachChild(hasThat)) {
        if ((base = this)[name = this.aSource] instanceof Existence) {
          base = base[name];
          name = 'it';
        }
        if (base[name].value !== 'that') {
          base[name] = Assign(Var('that'), base[name]);
        }
      }
      function hasThat(it) {
        var that;
        return it.value === 'that' || ((that = it.aSource) ? (that = it[that]) ? hasThat(that) : void 8 : it.eachChild(hasThat));
      }
      delete this.children;
      return ref$ = this[this.aSource], ref$.cond = true, ref$;
    },
    carp: function(msg, type) {
      type == null && (type = SyntaxError);
      throw type(msg + " on line " + (this.line || this.traverseChildren(function(it) {
        return it.line;
      })));
    },
    delegate: function(names, fn) {
      var i$,
          len$;
      for (i$ = 0, len$ = names.length; i$ < len$; ++i$) {
        (fn$.call(this, names[i$]));
      }
      function fn$(name) {
        this[name] = function(it) {
          return fn.call(this, name, it);
        };
      }
    },
    children: [],
    terminator: ';',
    isComplex: YES,
    isStatement: NO,
    isAssignable: NO,
    isCallable: NO,
    isEmpty: NO,
    isArray: NO,
    isString: NO,
    isRegex: NO,
    isMatcher: function() {
      return this.isString() || this.isRegex();
    },
    assigns: NO,
    ripName: VOID,
    unfoldSoak: VOID,
    unfoldAssign: VOID,
    unparen: THIS,
    unwrap: THIS,
    maybeKey: THIS,
    expandSlice: THIS,
    varName: String,
    getAccessors: VOID,
    getCall: VOID,
    getDefault: VOID,
    getJump: VOID,
    invert: function() {
      return Unary('!', this, true);
    },
    invertCheck: function(it) {
      if (it.inverted) {
        return this.invert();
      } else {
        return this;
      }
    },
    addElse: function($else) {
      this['else'] = $else;
      return this;
    },
    makeReturn: function(ref, obj) {
      var items,
          kv,
          i,
          v;
      if (obj) {
        items = this instanceof Arr ? (this.items[0] == null || this.items[1] == null && this.carp('must specify both key and value for object comprehension'), this.items) : (kv = 'keyValue$', (function() {
          var i$,
              ref$,
              len$,
              results$ = [];
          for (i$ = 0, len$ = (ref$ = [Assign(Var(kv), this), Var(kv)]).length; i$ < len$; ++i$) {
            i = i$;
            v = ref$[i$];
            results$.push(Chain(v).add(Index(Literal(i))));
          }
          return results$;
        }.call(this)));
        return Assign(Chain(Var(ref)).add(Index(items[0], '.', true)), items[1]);
      } else if (ref) {
        return Call.make(JS(ref + '.push'), [this]);
      } else {
        return Return(this);
      }
    },
    show: String,
    toString: function(idt) {
      var tree,
          that;
      idt || (idt = '');
      tree = '\n' + idt + this.constructor.displayName;
      if (that = this.show()) {
        tree += ' ' + that;
      }
      this.eachChild(function(it) {
        tree += it.toString(idt + TAB);
      });
      return tree;
    },
    stringify: function(space) {
      return JSON.stringify(this, null, space);
    },
    toJSON: function() {
      return import$({type: this.constructor.displayName}, this);
    }
  };
  exports.parse = function(json) {
    return exports.fromJSON(JSON.parse(json));
  };
  exports.fromJSON = (function() {
    function fromJSON(it) {
      var that,
          node,
          key,
          val,
          i$,
          len$,
          v,
          results$ = [];
      if (!(it && typeof it === 'object')) {
        return it;
      }
      if (that = it.type) {
        node = clone$(exports[that].prototype);
        for (key in it) {
          val = it[key];
          node[key] = fromJSON(val);
        }
        return node;
      }
      if (it.length != null) {
        for (i$ = 0, len$ = it.length; i$ < len$; ++i$) {
          v = it[i$];
          results$.push(fromJSON(v));
        }
        return results$;
      } else {
        return it;
      }
    }
    return fromJSON;
  }());
  Negatable = {
    show: function() {
      return this.negated && '!';
    },
    invert: function() {
      this.negated = !this.negated;
      return this;
    }
  };
  exports.Block = Block = (function(superclass) {
    var prototype = extend$((import$(Block, superclass).displayName = 'Block', Block), superclass).prototype,
        constructor = Block;
    function Block(body) {
      var this$ = this instanceof ctor$ ? this : new ctor$;
      body || (body = []);
      if ('length' in body) {
        this$.lines = body;
      } else {
        this$.lines = [];
        this$.add(body);
      }
      return this$;
    }
    function ctor$() {}
    ctor$.prototype = prototype;
    Block.prototype.children = ['lines'];
    Block.prototype.toJSON = function() {
      delete this.back;
      return superclass.prototype.toJSON.call(this);
    };
    Block.prototype.add = function(it) {
      var that,
          ref$;
      it = it.unparen();
      switch (false) {
        case !(that = this.back):
          that.add(it);
          break;
        case !(that = it.lines):
          (ref$ = this.lines).push.apply(ref$, that);
          break;
        default:
          this.lines.push(it);
          if (that = (ref$ = it.back, delete it.back, ref$)) {
            this.back = that;
          }
      }
      return this;
    };
    Block.prototype.prepend = function() {
      var ref$;
      (ref$ = this.lines).splice.apply(ref$, [this.neck(), 0].concat(slice$.call(arguments)));
      return this;
    };
    Block.prototype.pipe = function(target, type) {
      var args;
      args = type === '|>' ? this.lines.pop() : target;
      if (toString$.call(args).slice(8, -1) !== 'Array') {
        args = [args];
      }
      switch (type) {
        case '|>':
          this.lines.push(Call.make(target, args, {pipe: true}));
          break;
        case '<|':
          this.lines.push(Call.make(this.lines.pop(), args));
      }
      return this;
    };
    Block.prototype.unwrap = function() {
      if (this.lines.length === 1) {
        return this.lines[0];
      } else {
        return this;
      }
    };
    Block.prototype.chomp = function() {
      var lines,
          i,
          that;
      lines = this.lines;
      i = lines.length;
      while (that = lines[--i]) {
        if (!that.comment) {
          break;
        }
      }
      lines.length = i + 1;
      return this;
    };
    Block.prototype.neck = function() {
      var pos,
          i$,
          ref$,
          len$,
          x;
      pos = 0;
      for (i$ = 0, len$ = (ref$ = this.lines).length; i$ < len$; ++i$) {
        x = ref$[i$];
        if (!(x.comment || x instanceof Literal)) {
          break;
        }
        ++pos;
      }
      return pos;
    };
    Block.prototype.isComplex = function() {
      var ref$;
      return this.lines.length > 1 || ((ref$ = this.lines[0]) != null ? ref$.isComplex() : void 8);
    };
    prototype.delegate(['isCallable', 'isArray', 'isString', 'isRegex'], function(it) {
      var ref$,
          ref1$;
      return (ref$ = (ref1$ = this.lines)[ref1$.length - 1]) != null ? ref$[it]() : void 8;
    });
    Block.prototype.getJump = function(it) {
      var i$,
          ref$,
          len$,
          node,
          that;
      for (i$ = 0, len$ = (ref$ = this.lines).length; i$ < len$; ++i$) {
        node = ref$[i$];
        if (that = node.getJump(it)) {
          return that;
        }
      }
    };
    Block.prototype.makeReturn = function() {
      var that,
          ref$,
          key$,
          ref1$;
      this.chomp();
      if (that = (ref1$ = ref$ = this.lines)[key$ = ref1$.length - 1] != null ? ref$[key$] = (ref$ = ref$[key$]).makeReturn.apply(ref$, arguments) : void 8) {
        if (that instanceof Return && !that.it) {
          --this.lines.length;
        }
      }
      return this;
    };
    Block.prototype.compile = function(o, level) {
      var tab,
          codes,
          i$,
          ref$,
          len$,
          node,
          code;
      level == null && (level = o.level);
      if (level) {
        return this.compileExpressions(o, level);
      }
      o.block = this;
      tab = o.indent;
      codes = [];
      for (i$ = 0, len$ = (ref$ = this.lines).length; i$ < len$; ++i$) {
        node = ref$[i$];
        node = node.unfoldSoak(o) || node;
        if (snEmpty(code = (node.front = true, node).compile(o, level))) {
          continue;
        }
        codes.push(tab);
        codes.push(code);
        node.isStatement() || codes.push(node.terminator);
        codes.push('\n');
      }
      codes.pop();
      return sn.apply(null, [null].concat(slice$.call(codes)));
    };
    Block.prototype.compileRoot = function(options) {
      var o,
          that,
          ref$,
          bare,
          prefix,
          ref1$,
          code,
          result;
      o = (import$({
        level: LEVEL_TOP,
        scope: this.scope = Scope.root = new Scope
      }, options));
      if (that = (ref$ = o.saveScope, delete o.saveScope, ref$)) {
        this.scope = Scope.root = o.scope = that.savedScope || (that.savedScope = o.scope);
      }
      delete o.filename;
      o.indent = (bare = (ref$ = o.bare, delete o.bare, ref$)) ? '' : TAB;
      if (/^\s*(?:[/#]|javascript:)/.test((ref$ = this.lines[0]) != null ? ref$.code : void 8)) {
        prefix = this.lines.shift().code + '\n';
      }
      if ((ref1$ = o.eval, delete o.eval, ref1$) && this.chomp().lines.length) {
        if (bare) {
          this.lines.push(Parens(this.lines.pop()));
        } else {
          this.makeReturn();
        }
      }
      code = [this.compileWithDeclarations(o)];
      bare || (code = ["(function(){\n"].concat(slice$.call(code), ["\n}).call(this);\n"]));
      return result = sn.apply(null, [null, prefix || []].concat(slice$.call(code)));
    };
    Block.prototype.compileWithDeclarations = function(o) {
      var pre,
          i,
          rest,
          post,
          that;
      o.level = LEVEL_TOP;
      pre = [];
      if (i = this.neck()) {
        rest = this.lines.splice(i, 9e9);
        pre = [this.compile(o), "\n"];
        this.lines = rest;
      }
      if (snEmpty(post = this.compile(o))) {
        return sn(this, pre[0] || []);
      }
      return sn.apply(null, [null].concat(slice$.call(pre), [(that = this.scope) ? that.emit(post, o.indent) : post]));
    };
    Block.prototype.compileExpressions = function(o, level) {
      var lines,
          i,
          that,
          code,
          last,
          i$,
          len$,
          node;
      lines = this.chomp().lines;
      i = -1;
      while (that = lines[++i]) {
        if (that.comment) {
          lines.splice(i--, 1);
        }
      }
      if (!lines.length) {
        lines.push(Literal('void'));
      }
      lines[0].front = this.front;
      lines[lines.length - 1]['void'] = this['void'];
      if (!lines[1]) {
        return lines[0].compile(o, level);
      }
      code = [];
      last = lines.pop();
      for (i$ = 0, len$ = lines.length; i$ < len$; ++i$) {
        node = lines[i$];
        code.push((node['void'] = true, node).compile(o, LEVEL_PAREN), ', ');
      }
      code.push(last.compile(o, LEVEL_PAREN));
      if (level < LEVEL_LIST) {
        return sn.apply(null, [null].concat(slice$.call(code)));
      } else {
        return sn.apply(null, [null, "("].concat(slice$.call(code), [")"]));
      }
    };
    return Block;
  }(Node));
  Atom = (function(superclass) {
    var prototype = extend$((import$(Atom, superclass).displayName = 'Atom', Atom), superclass).prototype,
        constructor = Atom;
    Atom.prototype.show = function() {
      return this.value;
    };
    Atom.prototype.isComplex = NO;
    function Atom() {
      Atom.superclass.apply(this, arguments);
    }
    return Atom;
  }(Node));
  exports.Literal = Literal = (function(superclass) {
    var prototype = extend$((import$(Literal, superclass).displayName = 'Literal', Literal), superclass).prototype,
        constructor = Literal;
    function Literal(value) {
      var this$ = this instanceof ctor$ ? this : new ctor$;
      this$.value = value;
      if (value.js) {
        return JS(value + "", true);
      }
      if (value === 'super') {
        return new Super;
      }
      return this$;
    }
    function ctor$() {}
    ctor$.prototype = prototype;
    Literal.prototype.isEmpty = function() {
      var ref$;
      return (ref$ = this.value) === 'void' || ref$ === 'null';
    };
    Literal.prototype.isCallable = function() {
      var ref$;
      return (ref$ = this.value) === 'this' || ref$ === 'eval' || ref$ === '..';
    };
    Literal.prototype.isString = function() {
      return 0 <= '\'"'.indexOf((this.value + "").charAt());
    };
    Literal.prototype.isRegex = function() {
      return (this.value + "").charAt() === '/';
    };
    Literal.prototype.isComplex = function() {
      return this.isRegex() || this.value === 'debugger';
    };
    Literal.prototype.isWhat = function() {
      switch (false) {
        case !this.isEmpty():
          return 'empty';
        case !this.isCallable():
          return 'callable';
        case !this.isString():
          return 'string';
        case !this.isRegex():
          return 'regex';
        case !this.isComplex():
          return 'complex';
        default:
      }
    };
    Literal.prototype.varName = function() {
      if (/^\w+$/.test(this.value)) {
        return '$' + this.value;
      } else {
        return '';
      }
    };
    Literal.prototype.makeReturn = function(it) {
      if (!it && this.value === 'debugger') {
        return this;
      } else {
        return superclass.prototype.makeReturn.apply(this, arguments);
      }
    };
    Literal.prototype.maybeKey = function() {
      if (ID.test(this.value)) {
        return Key(this.value);
      } else {
        return this;
      }
    };
    Literal.prototype.compile = function(o, level) {
      var val,
          ref$;
      level == null && (level = o.level);
      switch (val = this.value + "") {
        case 'this':
          return sn(this, ((ref$ = o.scope.fun) != null ? ref$.bound : void 8) || val);
        case 'void':
          if (!level) {
            return sn(this, '');
          }
          val += ' 8';
        case 'null':
          if (level === LEVEL_CALL) {
            this.carp('invalid use of ' + this.value);
          }
          break;
        case 'on':
        case 'yes':
          val = 'true';
          break;
        case 'off':
        case 'no':
          val = 'false';
          break;
        case '*':
          this.carp('stray star');
          break;
        case '..':
          if (!(val = o.ref)) {
            this.carp('stray reference');
          }
          this.cascadee || (val.erred = true);
          break;
        case 'debugger':
          if (level) {
            return sn(this, "(function(){ debugger; }())");
          }
      }
      return sn(this, snSafe(val));
    };
    return Literal;
  }(Atom));
  exports.Var = Var = (function(superclass) {
    var prototype = extend$((import$(Var, superclass).displayName = 'Var', Var), superclass).prototype,
        constructor = Var;
    function Var(value) {
      var this$ = this instanceof ctor$ ? this : new ctor$;
      this$.value = value;
      return this$;
    }
    function ctor$() {}
    ctor$.prototype = prototype;
    prototype.isAssignable = prototype.isCallable = YES;
    Var.prototype.assigns = function(it) {
      return it === this.value;
    };
    Var.prototype.maybeKey = function() {
      var ref$;
      return ref$ = Key(this.value), ref$.line = this.line, ref$;
    };
    Var.prototype.varName = prototype.show;
    Var.prototype.compile = function(o) {
      return sn(this, this.temp ? o.scope.free(this.value) : this.value);
    };
    return Var;
  }(Atom));
  exports.Key = Key = (function(superclass) {
    var prototype = extend$((import$(Key, superclass).displayName = 'Key', Key), superclass).prototype,
        constructor = Key;
    function Key(name, reserved) {
      var this$ = this instanceof ctor$ ? this : new ctor$;
      this$.reserved = reserved || name.reserved;
      this$.name = '' + name;
      return this$;
    }
    function ctor$() {}
    ctor$.prototype = prototype;
    Key.prototype.isComplex = NO;
    Key.prototype.assigns = function(it) {
      return it === this.name;
    };
    Key.prototype.varName = function() {
      var name;
      name = this.name;
      if (this.reserved || (name === 'arguments' || name === 'eval')) {
        return "$" + name;
      } else {
        return name;
      }
    };
    Key.prototype.show = function() {
      if (this.reserved) {
        return "'" + this.name + "'";
      } else {
        return this.name;
      }
    };
    Key.prototype.compile = function() {
      return sn(this, this.show());
    };
    return Key;
  }(Node));
  exports.Index = Index = (function(superclass) {
    var prototype = extend$((import$(Index, superclass).displayName = 'Index', Index), superclass).prototype,
        constructor = Index;
    function Index(key, symbol, init) {
      var k,
          this$ = this instanceof ctor$ ? this : new ctor$;
      symbol || (symbol = '.');
      if (init && key instanceof Arr) {
        switch (key.items.length) {
          case 1:
            if (!((k = key.items[0]) instanceof Splat)) {
              key = Parens(k);
            }
        }
      }
      switch (symbol) {
        case '[]':
          this$.vivify = Arr;
          break;
        case '{}':
          this$.vivify = Obj;
          break;
        default:
          if ('=' === symbol.slice(-1)) {
            this$.assign = symbol.slice(1);
          }
      }
      this$.key = key;
      this$.symbol = symbol;
      return this$;
    }
    function ctor$() {}
    ctor$.prototype = prototype;
    Index.prototype.children = ['key'];
    Index.prototype.show = function() {
      return [this.soak ? '?' : void 8] + this.symbol;
    };
    Index.prototype.isComplex = function() {
      return this.key.isComplex();
    };
    Index.prototype.varName = function() {
      var ref$;
      return ((ref$ = this.key) instanceof Key || ref$ instanceof Literal) && this.key.varName();
    };
    Index.prototype.compile = function(o) {
      var code;
      code = this.key.compile(o, LEVEL_PAREN);
      if (this.key instanceof Key && '\'' !== code.toString().charAt(0)) {
        return sn(this, ".", code);
      } else {
        return sn(this, "[", code, "]");
      }
    };
    return Index;
  }(Node));
  exports.Slice = Slice = (function(superclass) {
    var prototype = extend$((import$(Slice, superclass).displayName = 'Slice', Slice), superclass).prototype,
        constructor = Slice;
    function Slice(arg$) {
      var this$ = this instanceof ctor$ ? this : new ctor$;
      this$.type = arg$.type, this$.target = arg$.target, this$.from = arg$.from, this$.to = arg$.to;
      this$.from == null && (this$.from = Literal(0));
      if (this$.to && this$.type === 'to') {
        this$.to = Binary('+', this$.to, Literal('1'));
      }
      return this$;
    }
    function ctor$() {}
    ctor$.prototype = prototype;
    Slice.prototype.children = ['target', 'from', 'to'];
    Slice.prototype.show = function() {
      return this.type;
    };
    Slice.prototype.compileNode = function(o) {
      var args;
      if (this.to && this.type === 'to') {
        this.to = Binary('||', this.to, Literal('9e9'));
      }
      args = [this.target, this.from];
      if (this.to) {
        args.push(this.to);
      }
      return Chain(Var(util('slice'))).add(Index(Key('call'), '.', true)).add(Call(args)).compile(o);
    };
    return Slice;
  }(Node));
  exports.Chain = Chain = (function(superclass) {
    var prototype = extend$((import$(Chain, superclass).displayName = 'Chain', Chain), superclass).prototype,
        constructor = Chain;
    function Chain(head, tails) {
      var this$ = this instanceof ctor$ ? this : new ctor$;
      if (!tails && head instanceof Chain) {
        return head;
      }
      this$.head = head;
      this$.tails = tails || [];
      return this$;
    }
    function ctor$() {}
    ctor$.prototype = prototype;
    Chain.prototype.children = ['head', 'tails'];
    Chain.prototype.add = function(it) {
      var last,
          ref$,
          index,
          ref1$,
          bi,
          logics,
          call,
          f;
      if (this.tails.length) {
        last = (ref$ = this.tails)[ref$.length - 1];
        if (last instanceof Call && ((ref$ = last.partialized) != null ? ref$.length : void 8) === 1 && it.args.length === 1) {
          index = last.partialized[0].head.value;
          delete last.partialized;
          last.args[index] = it.args[0];
          return this;
        }
      }
      if (this.head instanceof Existence) {
        ref1$ = Chain(this.head.it), this.head = ref1$.head, this.tails = ref1$.tails;
        it.soak = true;
      }
      this.tails.push(it);
      bi = this.head instanceof Parens && this.head.it instanceof Binary && !this.head.it.partial ? this.head.it : this.head instanceof Binary && !this.head.partial ? this.head : void 8;
      if (this.head instanceof Super) {
        if (!this.head.called && it instanceof Call && !it.method) {
          it.method = '.call';
          it.args.unshift(Literal('this'));
          this.head.called = true;
        } else if (!this.tails[1] && ((ref1$ = it.key) != null ? ref1$.name : void 8) === 'prototype') {
          this.head.sproto = true;
        }
      } else if (it instanceof Call && this.tails.length === 1 && bi && in$(bi.op, logics = ['&&', '||', 'xor'])) {
        call = it;
        f = function(x, key) {
          var y;
          y = x[key];
          if (y instanceof Binary && in$(y.op, logics)) {
            f(y, 'first');
            return f(y, 'second');
          } else {
            return x[key] = Chain(y).autoCompare(call.args);
          }
        };
        f(bi, 'first');
        f(bi, 'second');
        return bi;
      }
      return this;
    };
    Chain.prototype.autoCompare = function(target) {
      var test;
      test = this.head;
      switch (false) {
        case !(test instanceof Literal):
          return Binary('===', test, target[0]);
        case !(test instanceof Unary && test.it instanceof Literal):
          return Binary('===', test, target[0]);
        case !(test instanceof Arr || test instanceof Obj):
          return Binary('====', test, target[0]);
        case !(test instanceof Var && test.value === '_'):
          return Literal('true');
        default:
          return this.add(Call(target)) || [];
      }
    };
    Chain.prototype.flipIt = function() {
      this.flip = true;
      return this;
    };
    Chain.prototype.unwrap = function() {
      if (this.tails.length) {
        return this;
      } else {
        return this.head;
      }
    };
    prototype.delegate(['getJump', 'assigns', 'isStatement', 'isString'], function(it, arg) {
      return !this.tails.length && this.head[it](arg);
    });
    Chain.prototype.isComplex = function() {
      return this.tails.length || this.head.isComplex();
    };
    Chain.prototype.isCallable = function() {
      var that,
          ref$;
      if (that = (ref$ = this.tails)[ref$.length - 1]) {
        return !((ref$ = that.key) != null && ref$.items);
      } else {
        return this.head.isCallable();
      }
    };
    Chain.prototype.isArray = function() {
      var that,
          ref$;
      if (that = (ref$ = this.tails)[ref$.length - 1]) {
        return that.key instanceof Arr;
      } else {
        return this.head.isArray();
      }
    };
    Chain.prototype.isRegex = function() {
      return this.head.value === 'RegExp' && !this.tails[1] && this.tails[0] instanceof Call;
    };
    Chain.prototype.isAssignable = function() {
      var tail,
          ref$,
          i$,
          len$;
      if (!(tail = (ref$ = this.tails)[ref$.length - 1])) {
        return this.head.isAssignable();
      }
      if (!(tail instanceof Index) || tail.key instanceof List || tail.symbol === '.~') {
        return false;
      }
      for (i$ = 0, len$ = (ref$ = this.tails).length; i$ < len$; ++i$) {
        tail = ref$[i$];
        if (tail.assign) {
          return false;
        }
      }
      return true;
    };
    Chain.prototype.isSimpleAccess = function() {
      return this.tails.length === 1 && !this.head.isComplex() && !this.tails[0].isComplex();
    };
    Chain.prototype.makeReturn = function() {
      var ref$;
      if (this.tails.length) {
        return superclass.prototype.makeReturn.apply(this, arguments);
      } else {
        return (ref$ = this.head).makeReturn.apply(ref$, arguments);
      }
    };
    Chain.prototype.getCall = function() {
      var tail,
          ref$;
      return (tail = (ref$ = this.tails)[ref$.length - 1]) instanceof Call && tail;
    };
    Chain.prototype.varName = function() {
      var ref$,
          ref1$;
      return (ref$ = (ref1$ = this.tails)[ref1$.length - 1]) != null ? ref$.varName() : void 8;
    };
    Chain.prototype.cacheReference = function(o) {
      var name,
          ref$,
          base,
          ref,
          bref,
          nref;
      name = (ref$ = this.tails)[ref$.length - 1];
      if (!this.isAssignable()) {
        return this.unwrap().cache(o, true);
      }
      if (this.tails.length < 2 && !this.head.isComplex() && !(name != null && name.isComplex())) {
        return [this, this];
      }
      base = Chain(this.head, this.tails.slice(0, -1));
      if (base.isComplex()) {
        ref = o.scope.temporary();
        base = Chain(Assign(Var(ref), base));
        bref = (ref$ = Var(ref), ref$.temp = true, ref$);
      }
      if (!name) {
        return [base, bref];
      }
      if (name.isComplex()) {
        ref = o.scope.temporary('key');
        name = Index(Assign(Var(ref), name.key));
        nref = Index((ref$ = Var(ref), ref$.temp = true, ref$));
      }
      return [base.add(name), Chain(bref || base.head, [nref || name])];
    };
    Chain.prototype.compileNode = function(o) {
      var head,
          tails,
          that,
          i$,
          len$,
          t,
          hasPartial,
          pre,
          rest,
          broken,
          partial,
          post,
          context,
          idt,
          func,
          base,
          news,
          ref$;
      if (this.flip) {
        util('flip');
        util('curry');
      }
      head = this.head, tails = this.tails;
      head.front = this.front;
      head.newed = this.newed;
      if (!tails.length) {
        return head.compile(o);
      }
      if (that = this.unfoldAssign(o)) {
        return that.compile(o);
      }
      for (i$ = 0, len$ = tails.length; i$ < len$; ++i$) {
        t = tails[i$];
        if (t.partialized) {
          hasPartial = true;
          break;
        }
      }
      if (hasPartial) {
        util('slice');
        pre = [];
        rest = [];
        for (i$ = 0, len$ = tails.length; i$ < len$; ++i$) {
          t = tails[i$];
          broken = broken || t.partialized != null;
          if (broken) {
            rest.push(t);
          } else {
            pre.push(t);
          }
        }
        if (rest != null) {
          partial = rest[0], post = slice$.call(rest, 1);
        }
        this.tails = pre;
        context = pre.length ? Chain(head, slice$.call(pre, 0, -1)) : Literal('this');
        return Chain(Chain(Var(util('partialize'))).add(Index(Key('apply'))).add(Call([context, Arr([this, Arr(partial.args), Arr(partial.partialized)])])), post).compile(o);
      }
      if (tails[0] instanceof Call && !head.isCallable()) {
        this.carp('invalid callee');
      }
      this.expandSlice(o);
      this.expandVivify();
      this.expandBind(o);
      this.expandSplat(o);
      this.expandStar(o);
      if (this.splattedNewArgs) {
        idt = o.indent + TAB;
        func = Chain(this.head, tails.slice(0, -1));
        return sn(null, "(function(func, args, ctor) {\n" + idt + "ctor.prototype = func.prototype;\n" + idt + "var child = new ctor, result = func.apply(child, args), t;\n" + idt + "return (t = typeof result)  == \"object\" || t == \"function\" ? result || child : child;\n" + TAB + "})(", func.compile(o), ", ", this.splattedNewArgs, ", function(){})");
      }
      if (!this.tails.length) {
        return this.head.compile(o);
      }
      base = [this.head.compile(o, LEVEL_CALL)];
      news = [];
      rest = [];
      for (i$ = 0, len$ = (ref$ = this.tails).length; i$ < len$; ++i$) {
        t = ref$[i$];
        if (t['new']) {
          news.push('new ');
        }
        rest.push(t.compile(o));
      }
      if ('.' === rest.join("").charAt(0) && SIMPLENUM.test(base[0].toString())) {
        base.push(' ');
      }
      return sn.apply(null, [null].concat(slice$.call(news), slice$.call(base), slice$.call(rest)));
    };
    Chain.prototype.unfoldSoak = function(o) {
      var that,
          ref$,
          i$,
          len$,
          i,
          node,
          ref1$,
          bust,
          test;
      if (that = this.head.unfoldSoak(o)) {
        (ref$ = that.then.tails).push.apply(ref$, this.tails);
        return that;
      }
      for (i$ = 0, len$ = (ref$ = this.tails).length; i$ < len$; ++i$) {
        i = i$;
        node = ref$[i$];
        if (ref1$ = node.soak, delete node.soak, ref1$) {
          bust = Chain(this.head, this.tails.splice(0, i));
          if (node.assign && !bust.isAssignable()) {
            node.carp('invalid accessign');
          }
          if (i && (node.assign || node instanceof Call)) {
            ref1$ = bust.cacheReference(o), test = ref1$[0], bust = ref1$[1];
            if (bust instanceof Chain) {
              (ref1$ = this.tails).unshift.apply(ref1$, bust.tails);
              bust = bust.head;
            }
            this.head = bust;
          } else {
            ref1$ = bust.unwrap().cache(o), test = ref1$[0], this.head = ref1$[1];
          }
          test = node instanceof Call ? JS("typeof " + test.compile(o, LEVEL_OP) + " == 'function'") : Existence(test);
          return ref1$ = If(test, this), ref1$.soak = true, ref1$.cond = this.cond, ref1$['void'] = this['void'], ref1$;
        }
      }
    };
    Chain.prototype.unfoldAssign = function(o) {
      var that,
          ref$,
          i$,
          len$,
          i,
          index,
          op,
          left,
          lefts,
          rites,
          j$,
          len1$,
          node,
          ref1$;
      if (that = this.head.unfoldAssign(o)) {
        (ref$ = that.right.tails).push.apply(ref$, this.tails);
        return that;
      }
      for (i$ = 0, len$ = (ref$ = this.tails).length; i$ < len$; ++i$) {
        i = i$;
        index = ref$[i$];
        if (op = index.assign) {
          index.assign = '';
          left = Chain(this.head, this.tails.splice(0, i)).expandSlice(o).unwrap();
          if (left instanceof Arr) {
            lefts = left.items;
            rites = (this.head = Arr()).items;
            for (j$ = 0, len1$ = lefts.length; j$ < len1$; ++j$) {
              i = j$;
              node = lefts[j$];
              ref1$ = Chain(node).cacheReference(o), rites[i] = ref1$[0], lefts[i] = ref1$[1];
            }
          } else {
            ref1$ = Chain(left).cacheReference(o), left = ref1$[0], this.head = ref1$[1];
          }
          if (op === '=') {
            op = ':=';
          }
          return ref1$ = Assign(left, this, op), ref1$.access = true, ref1$;
        }
      }
    };
    Chain.prototype.expandSplat = function(o) {
      var tails,
          i,
          call,
          args,
          ctx,
          ref$;
      tails = this.tails;
      i = -1;
      while (call = tails[++i]) {
        if (!(args = call.args)) {
          continue;
        }
        ctx = call.method === '.call' && (args = args.concat()).shift();
        if (!!snEmpty(args = Splat.compileArray(o, args, true))) {
          continue;
        }
        if (call['new']) {
          this.splattedNewArgs = args;
        } else {
          if (!ctx && tails[i - 1] instanceof Index) {
            ref$ = Chain(this.head, tails.splice(0, i - 1)).cache(o, true), this.head = ref$[0], ctx = ref$[1];
            i = 0;
          }
          call.method = '.apply';
          call.args = [ctx || Literal('null'), JS(args)];
        }
      }
    };
    Chain.prototype.expandVivify = function() {
      var tails,
          i,
          that,
          ref$,
          ref1$;
      tails = this.tails;
      i = 0;
      while (i < tails.length) {
        if (that = (ref1$ = (ref$ = tails[i++]).vivify, delete ref$.vivify, ref1$)) {
          this.head = Assign(Chain(this.head, tails.splice(0, i)), that(), '=', '||');
          i = 0;
        }
      }
    };
    Chain.prototype.expandBind = function(o) {
      var tails,
          i,
          that,
          obj,
          key,
          call;
      tails = this.tails;
      i = -1;
      while (that = tails[++i]) {
        if (that.symbol !== '.~') {
          continue;
        }
        that.symbol = '';
        obj = Chain(this.head, tails.splice(0, i)).unwrap();
        key = tails.shift().key;
        call = Call.make(Util('bind'), [obj, (key.reserved = true, key)]);
        this.head = this.newed ? Parens(call, true) : call;
        i = -1;
      }
    };
    Chain.prototype.expandStar = function(o) {
      var tails,
          i,
          that,
          stars,
          ref$,
          sub,
          ref,
          temps,
          value,
          i$,
          len$,
          star;
      tails = this.tails;
      i = -1;
      while (that = tails[++i]) {
        if (that.args || that.stars || that.key instanceof Key) {
          continue;
        }
        stars = that.stars = [];
        that.eachChild(seek);
        if (!stars.length) {
          continue;
        }
        ref$ = Chain(this.head, tails.splice(0, i)).unwrap().cache(o), sub = ref$[0], ref = ref$[1], temps = ref$[2];
        value = Chain(ref, [Index(Key('length'))]).compile(o);
        for (i$ = 0, len$ = stars.length; i$ < len$; ++i$) {
          star = stars[i$];
          star.value = value;
          star.isAssignable = YES;
        }
        this.head = JS(sub.compile(o, LEVEL_CALL) + tails.shift().compile(o));
        if (temps) {
          o.scope.free(temps[0]);
        }
        i = -1;
      }
      function seek(it) {
        if (it.value === '*') {
          stars.push(it);
        } else if (!(it instanceof Index)) {
          it.eachChild(seek);
        }
      }
    };
    Chain.prototype.expandSlice = function(o, assign) {
      var tails,
          i,
          tail,
          ref$,
          x;
      tails = this.tails;
      i = -1;
      while (tail = tails[++i]) {
        if ((ref$ = tail.key) != null && ref$.items) {
          if (tails[i + 1] instanceof Call) {
            tail.carp('calling a slice');
          }
          x = tails.splice(0, i + 1);
          x = x.pop().key.toSlice(o, Chain(this.head, x).unwrap(), tail.symbol, assign);
          this.head = (x.front = this.front, x);
          i = -1;
        }
      }
      return this;
    };
    return Chain;
  }(Node));
  exports.Call = Call = (function(superclass) {
    var prototype = extend$((import$(Call, superclass).displayName = 'Call', Call), superclass).prototype,
        constructor = Call;
    function Call(args) {
      var splat,
          i$,
          len$,
          i,
          a,
          ref$,
          this$ = this instanceof ctor$ ? this : new ctor$;
      args || (args = []);
      if (args.length === 1 && (splat = args[0]) instanceof Splat) {
        if (splat.filler) {
          this$.method = '.call';
          args[0] = Literal('this');
          args[1] = Splat(Literal('arguments'));
        } else if (splat.it instanceof Arr) {
          args = splat.it.items;
        }
      } else {
        for (i$ = 0, len$ = args.length; i$ < len$; ++i$) {
          i = i$;
          a = args[i$];
          if (a.value === '_') {
            args[i] = Chain(Literal('void'));
            args[i].placeholder = true;
            ((ref$ = this$.partialized) != null ? ref$ : this$.partialized = []).push(Chain(Literal(i)));
          }
        }
      }
      this$.args = args;
      return this$;
    }
    function ctor$() {}
    ctor$.prototype = prototype;
    Call.prototype.children = ['args'];
    Call.prototype.show = function() {
      return [this['new']] + [this.method] + [this.soak ? '?' : void 8];
    };
    Call.prototype.compile = function(o) {
      var code,
          i$,
          ref$,
          len$,
          i,
          a;
      code = [sn(this, this.method || '', '(') + (this.pipe ? "\n" + o.indent : '')];
      for (i$ = 0, len$ = (ref$ = this.args).length; i$ < len$; ++i$) {
        i = i$;
        a = ref$[i$];
        code.push(i ? ', ' : '', a.compile(o, LEVEL_LIST));
      }
      code.push(sn(this, ')'));
      return sn.apply(null, [null].concat(slice$.call(code)));
    };
    Call.make = function(callee, args, opts) {
      var call;
      call = Call(args);
      if (opts) {
        import$(call, opts);
      }
      return Chain(callee).add(call);
    };
    Call.block = function(fun, args, method) {
      var ref$,
          ref1$;
      return ref$ = Parens(Chain(fun, [(ref1$ = Call(args), ref1$.method = method, ref1$)]), true), ref$.calling = true, ref$;
    };
    Call.back = function(params, node, bound, curried, hushed, generator) {
      var fun,
          ref$,
          args,
          index,
          i$,
          len$,
          a;
      fun = Fun(params, void 8, bound, curried, hushed, generator);
      if (node instanceof Label) {
        fun.name = node.label;
        fun.labeled = true;
        node = node.it;
      }
      if (!fun.hushed && (fun.hushed = node.op === '!')) {
        node = node.it;
      }
      if ((ref$ = node.getCall()) != null) {
        ref$.partialized = null;
      }
      args = (node.getCall() || (node = Chain(node).add(Call())).getCall()).args;
      index = 0;
      for (i$ = 0, len$ = args.length; i$ < len$; ++i$) {
        a = args[i$];
        if (a.placeholder) {
          break;
        }
        ++index;
      }
      return node.back = (args[index] = fun).body, node;
    };
    Call['let'] = function(args, body, generator) {
      var params,
          res$,
          i$,
          len$,
          i,
          a,
          that,
          gotThis;
      generator == null && (generator = false);
      res$ = [];
      for (i$ = 0, len$ = args.length; i$ < len$; ++i$) {
        i = i$;
        a = args[i$];
        if (that = a.op === '=' && !a.logic && a.right) {
          args[i] = that;
          if (i === 0 && (gotThis = a.left.value === 'this')) {
            continue;
          }
          res$.push(a.left);
        } else {
          res$.push(Var(a.varName() || a.carp('invalid "let" argument')));
        }
      }
      params = res$;
      gotThis || args.unshift(Literal('this'));
      return this.block(Fun(params, body, null, null, null, generator), args, '.call');
    };
    return Call;
  }(Node));
  List = (function(superclass) {
    var prototype = extend$((import$(List, superclass).displayName = 'List', List), superclass).prototype,
        constructor = List;
    List.prototype.children = ['items'];
    List.prototype.show = function() {
      return this.name;
    };
    List.prototype.named = function(name) {
      this.name = name;
      return this;
    };
    List.prototype.isEmpty = function() {
      return !this.items.length;
    };
    List.prototype.assigns = function(it) {
      var i$,
          ref$,
          len$,
          node;
      for (i$ = 0, len$ = (ref$ = this.items).length; i$ < len$; ++i$) {
        node = ref$[i$];
        if (node.assigns(it)) {
          return true;
        }
      }
    };
    List.compile = function(o, items, deepEq) {
      var indent,
          level,
          code,
          i,
          that,
          target;
      switch (items.length) {
        case 0:
          return '';
        case 1:
          return items[0].compile(o, LEVEL_LIST);
      }
      indent = o.indent, level = o.level;
      o.indent = indent + TAB;
      o.level = LEVEL_LIST;
      code = [items[i = 0].compile(o)];
      while (that = items[++i]) {
        code.push(', ');
        target = that;
        if (deepEq) {
          if (target instanceof Var && target.value === '_') {
            target = Obj([Prop(Key('__placeholder__'), Literal(true))]);
          } else if (target instanceof Obj || target instanceof Arr) {
            target.deepEq = true;
          }
        }
        code.push(target.compile(o));
      }
      if (~code.join("").indexOf('\n')) {
        code = ["\n" + o.indent].concat(slice$.call(code), ["\n" + indent]);
      }
      o.indent = indent;
      o.level = level;
      return sn.apply(null, [this].concat(slice$.call(code)));
    };
    function List() {
      List.superclass.apply(this, arguments);
    }
    return List;
  }(Node));
  exports.Obj = Obj = (function(superclass) {
    var prototype = extend$((import$(Obj, superclass).displayName = 'Obj', Obj), superclass).prototype,
        constructor = Obj;
    function Obj(items) {
      var this$ = this instanceof ctor$ ? this : new ctor$;
      this$.items = items || [];
      return this$;
    }
    function ctor$() {}
    ctor$.prototype = prototype;
    Obj.prototype.asObj = THIS;
    Obj.prototype.toSlice = function(o, base, symbol, assign) {
      var items,
          ref$,
          ref,
          temps,
          i$,
          len$,
          i,
          node,
          name,
          chain,
          logic,
          key,
          val;
      items = this.items;
      if (items.length > 1) {
        ref$ = base.cache(o), base = ref$[0], ref = ref$[1], temps = ref$[2];
      } else {
        ref = base;
      }
      for (i$ = 0, len$ = items.length; i$ < len$; ++i$) {
        i = i$;
        node = items[i$];
        if (node.comment) {
          continue;
        }
        if (node instanceof Prop || node instanceof Splat) {
          node[name = (ref$ = node.children)[ref$.length - 1]] = chain = Chain(base, [Index(node[name].maybeKey())]);
        } else {
          if (logic = node.getDefault()) {
            node = node.first;
          }
          if (node instanceof Parens) {
            ref$ = node.cache(o, true), key = ref$[0], node = ref$[1];
            if (assign) {
              ref$ = [node, key], key = ref$[0], node = ref$[1];
            }
            key = Parens(key);
          } else {
            key = node;
          }
          val = chain = Chain(base, [Index(node.maybeKey(), symbol)]);
          if (logic) {
            val = (logic.first = val, logic);
          }
          items[i] = Prop(key, val);
        }
        base = ref;
      }
      chain || this.carp('empty slice');
      if (temps) {
        (chain.head = Var(temps[0])).temp = true;
      }
      return this;
    };
    Obj.prototype.compileNode = function(o) {
      var items,
          code,
          idt,
          dic,
          i$,
          len$,
          i,
          node,
          logic,
          rest,
          ref$,
          multi,
          key,
          val;
      items = this.items;
      if (!items.length) {
        return sn(this, this.front ? '({})' : '{}');
      }
      code = [];
      idt = '\n' + (o.indent += TAB);
      dic = {};
      for (i$ = 0, len$ = items.length; i$ < len$; ++i$) {
        i = i$;
        node = items[i$];
        if (node.comment) {
          code.push(idt, node.compile(o));
          continue;
        }
        if (logic = node.getDefault()) {
          node = node.first;
        }
        if (node instanceof Splat || (node.key || node) instanceof Parens) {
          rest = items.slice(i);
          break;
        }
        if (logic) {
          if (node instanceof Prop) {
            node.val = (logic.first = node.val, logic);
          } else {
            node = Prop(node, (logic.first = node, logic));
          }
        }
        if (this.deepEq && node instanceof Prop) {
          if (node.val instanceof Var && node.val.value === '_') {
            node.val = Obj([Prop(Key('__placeholder__'), Literal(true))]);
          } else if ((ref$ = node.val) instanceof Obj || ref$ instanceof Arr) {
            node.val.deepEq = true;
          }
        }
        if (multi) {
          code.push(',');
        } else {
          multi = true;
        }
        code.push(idt);
        if (node instanceof Prop) {
          key = node.key, val = node.val;
          if (node.accessor) {
            code.push(node.compileAccessor(o, key = key.compile(o)));
          } else {
            val.ripName(key);
            code.push(key = key.compile(o), ": ", val.compile(o, LEVEL_LIST));
          }
        } else {
          code.push(key = node.compile(o), ": ", key);
        }
        ID.test(key) || (key = Function("return " + key)());
        if (!(dic[key + "."] ^= 1)) {
          node.carp("duplicate property \"" + key + "\"");
        }
      }
      if (code.join("")) {
        code.push('\n' + this.tab);
      }
      code = sn.apply(null, [null, sn(this, "{")].concat(slice$.call(code), [sn(this, "}")]));
      rest && (code = Import(JS(code), Obj(rest)).compile((o.indent = this.tab, o)));
      if (this.front && '{' === code.toString().charAt()) {
        return sn(null, "(", code, ")");
      } else {
        return code;
      }
    };
    return Obj;
  }(List));
  exports.Prop = Prop = (function(superclass) {
    var prototype = extend$((import$(Prop, superclass).displayName = 'Prop', Prop), superclass).prototype,
        constructor = Prop;
    function Prop(key, val) {
      var that,
          i$,
          len$,
          fun,
          this$ = this instanceof ctor$ ? this : new ctor$;
      this$.key = key;
      this$.val = val;
      if (key.value === '...') {
        return Splat(this$.val);
      }
      if (that = val.getAccessors()) {
        this$.val = that;
        for (i$ = 0, len$ = that.length; i$ < len$; ++i$) {
          fun = that[i$];
          fun.x = (fun.hushed = fun.params.length) ? 's' : 'g';
        }
        this$['accessor'] = 'accessor';
      }
      return this$;
    }
    function ctor$() {}
    ctor$.prototype = prototype;
    Prop.prototype.children = ['key', 'val'];
    Prop.prototype.show = function() {
      return this.accessor;
    };
    Prop.prototype.assigns = function(it) {
      var ref$;
      return typeof(ref$ = this.val).assigns == 'function' ? ref$.assigns(it) : void 8;
    };
    Prop.prototype.compileAccessor = function(o, key) {
      var funs,
          code,
          i$,
          len$,
          fun;
      funs = this.val;
      if (funs[1] && funs[0].params.length + funs[1].params.length !== 1) {
        funs[0].carp('invalid accessor parameter');
      }
      code = [];
      for (i$ = 0, len$ = funs.length; i$ < len$; ++i$) {
        fun = funs[i$];
        fun.accessor = true;
        code.push(fun.x, "et ", key, fun.compile(o, LEVEL_LIST).toString().slice(8), ',\n' + o.indent);
      }
      code.pop();
      return sn.apply(null, [null].concat(slice$.call(code)));
    };
    Prop.prototype.compileDescriptor = function(o) {
      var obj,
          i$,
          ref$,
          len$,
          fun;
      obj = Obj();
      for (i$ = 0, len$ = (ref$ = this.val).length; i$ < len$; ++i$) {
        fun = ref$[i$];
        obj.items.push(Prop(Key(fun.x + 'et'), fun));
      }
      obj.items.push(Prop(Key('configurable'), Literal(true)));
      obj.items.push(Prop(Key('enumerable'), Literal(true)));
      return obj.compile(o);
    };
    return Prop;
  }(Node));
  exports.Arr = Arr = (function(superclass) {
    var prototype = extend$((import$(Arr, superclass).displayName = 'Arr', Arr), superclass).prototype,
        constructor = Arr;
    function Arr(items) {
      var this$ = this instanceof ctor$ ? this : new ctor$;
      this$.items = items || [];
      return this$;
    }
    function ctor$() {}
    ctor$.prototype = prototype;
    Arr.prototype.isArray = YES;
    Arr.prototype.asObj = function() {
      var i,
          item;
      return Obj((function() {
        var i$,
            ref$,
            len$,
            results$ = [];
        for (i$ = 0, len$ = (ref$ = this.items).length; i$ < len$; ++i$) {
          i = i$;
          item = ref$[i$];
          results$.push(Prop(Literal(i), item));
        }
        return results$;
      }.call(this)));
    };
    Arr.prototype.toSlice = function(o, base, symbol) {
      var items,
          ref$,
          ref,
          i$,
          len$,
          i,
          item,
          splat,
          chain;
      items = this.items;
      if (items.length > 1) {
        ref$ = base.cache(o), base = ref$[0], ref = ref$[1];
      } else {
        ref = base;
      }
      for (i$ = 0, len$ = items.length; i$ < len$; ++i$) {
        i = i$;
        item = items[i$];
        if (splat = item instanceof Splat) {
          item = item.it;
        }
        if (item.isEmpty()) {
          continue;
        }
        chain = Chain(base, [Index(item, symbol)]);
        items[i] = splat ? Splat(chain) : chain;
        base = ref;
      }
      chain || this.carp('empty slice');
      return this;
    };
    Arr.prototype.compile = function(o) {
      var items,
          code;
      items = this.items;
      if (!items.length) {
        return sn(this, '[]');
      }
      if (!snEmpty(code = Splat.compileArray(o, items))) {
        return this.newed ? sn(this, "(", code, ")") : sn(this, code);
      }
      return sn(null, sn(this, "["), List.compile(o, items, this.deepEq), sn(this, "]"));
    };
    Arr.maybe = function(nodes) {
      if (nodes.length === 1 && !(nodes[0] instanceof Splat)) {
        return nodes[0];
      }
      return constructor(nodes);
    };
    Arr.wrap = function(it) {
      return constructor([Splat((it.isArray = YES, it))]);
    };
    return Arr;
  }(List));
  exports.Yield = Yield = (function(superclass) {
    var prototype = extend$((import$(Yield, superclass).displayName = 'Yield', Yield), superclass).prototype,
        constructor = Yield;
    function Yield(op, it) {
      var this$ = this instanceof ctor$ ? this : new ctor$;
      this$.op = op;
      this$.it = it;
      return this$;
    }
    function ctor$() {}
    ctor$.prototype = prototype;
    Yield.prototype.children = ['it'];
    Yield.prototype.show = function() {
      if (this.op === 'yieldfrom') {
        return 'from';
      } else {
        return '';
      }
    };
    prototype.delegate(['isCallable'], function() {
      return true;
    });
    Yield.prototype.compileNode = function(o) {
      var code;
      code = [];
      if (this.op === 'yieldfrom') {
        code.push('yield*');
      } else {
        code.push('yield');
      }
      if (this.it) {
        code.push(" " + this.it.compile(o, LEVEL_OP + PREC.unary));
      }
      return sn.apply(null, [this, "("].concat(slice$.call(code), [")"]));
    };
    return Yield;
  }(Node));
  exports.Unary = Unary = (function(superclass) {
    var prototype = extend$((import$(Unary, superclass).displayName = 'Unary', Unary), superclass).prototype,
        constructor = Unary;
    function Unary(op, it, flag) {
      var that,
          i$,
          ref$,
          len$,
          node,
          this$ = this instanceof ctor$ ? this : new ctor$;
      if (it != null) {
        if (that = !flag && it.unaries) {
          that.push(op);
          return it;
        }
        switch (op) {
          case '!':
            if (flag) {
              break;
            }
            if (it instanceof Fun && !it.hushed) {
              return it.hushed = true, it;
            }
            return it.invert();
          case '++':
          case '--':
            if (flag) {
              this$.post = true;
            }
            break;
          case 'new':
            if (it instanceof Existence && !it.negated) {
              it = Chain(it).add(Call());
            }
            it.newed = true;
            for (i$ = 0, len$ = (ref$ = it.tails || '').length; i$ < len$; ++i$) {
              node = ref$[i$];
              if (node instanceof Call && !node['new']) {
                if (node.method === '.call') {
                  node.args.shift();
                }
                node['new'] = 'new';
                node.method = '';
                return it;
              }
            }
            break;
          case '~':
            if (it instanceof Fun && it.statement && !it.bound) {
              return it.bound = 'this$', it;
            }
        }
      }
      this$.op = op;
      this$.it = it;
      return this$;
    }
    function ctor$() {}
    ctor$.prototype = prototype;
    Unary.prototype.children = ['it'];
    Unary.prototype.show = function() {
      return [this.post ? '@' : void 8] + this.op;
    };
    Unary.prototype.isCallable = function() {
      var ref$;
      return ((ref$ = this.op) === 'do' || ref$ === 'new' || ref$ === 'delete') || this.it == null;
    };
    Unary.prototype.isArray = function() {
      return this.it instanceof Arr && this.it.items.length || this.it instanceof Chain && this.it.isArray();
    };
    Unary.prototype.isString = function() {
      var ref$;
      return (ref$ = this.op) === 'typeof' || ref$ === 'classof';
    };
    Unary.prototype.invert = function() {
      var ref$;
      if (this.op === '!' && ((ref$ = this.it.op) === '!' || ref$ === '<' || ref$ === '>' || ref$ === '<=' || ref$ === '>=' || ref$ === 'of' || ref$ === 'instanceof')) {
        return this.it;
      }
      return constructor('!', this, true);
    };
    Unary.prototype.unfoldSoak = function(o) {
      var ref$;
      return ((ref$ = this.op) === '++' || ref$ === '--' || ref$ === 'delete') && this.it != null && If.unfoldSoak(o, this, 'it');
    };
    Unary.prototype.getAccessors = function() {
      var items;
      if (this.op !== '~') {
        return;
      }
      if (this.it instanceof Fun) {
        return [this.it];
      }
      if (this.it instanceof Arr) {
        items = this.it.items;
        if (!items[2] && items[0] instanceof Fun && items[1] instanceof Fun) {
          return items;
        }
      }
    };
    function crement(it) {
      return {
        '++': 'in',
        '--': 'de'
      }[it] + 'crement';
    }
    Unary.prototype.compileNode = function(o) {
      var that,
          op,
          it,
          x,
          code;
      if (this.it == null) {
        return this.compileAsFunc(o);
      }
      if (that = this.compileSpread(o)) {
        return that;
      }
      op = this.op, it = this.it;
      switch (op) {
        case '!':
          it.cond = true;
          break;
        case 'new':
          it.isCallable() || it.carp('invalid constructor');
          break;
        case 'do':
          if (o.level === LEVEL_TOP && it instanceof Fun && it.isStatement()) {
            return sn(this, it.compile(o), " ", Unary('do', Var(it.name)).compile(o));
          }
          x = Parens(it instanceof Existence && !it.negated ? Chain(it).add(Call()) : Call.make(it));
          return sn(this, (x.front = this.front, x.newed = this.newed, x).compile(o));
        case 'delete':
          if (it instanceof Var || !it.isAssignable()) {
            this.carp('invalid delete');
          }
          if (o.level && !this['void']) {
            return this.compilePluck(o);
          }
          break;
        case '++':
        case '--':
          it.isAssignable() || this.carp('invalid ' + crement(op));
          if (that = it instanceof Var && o.scope.checkReadOnly(it.value)) {
            this.carp(crement(op) + " of " + that + " \"" + it.value + "\"", ReferenceError);
          }
          if (this.post) {
            it.front = this.front;
          }
          break;
        case '^^':
          return sn(this, util('clone'), "(", it.compile(o, LEVEL_LIST), ")");
        case 'jsdelete':
          return sn(this, "delete ", it.compile(o, LEVEL_LIST));
        case 'classof':
          return sn(this, util('toString'), ".call(", it.compile(o, LEVEL_LIST), ").slice(8, -1)");
      }
      code = [it.compile(o, LEVEL_OP + PREC.unary)];
      if (this.post) {
        code.push(op);
      } else {
        if ((op === 'new' || op === 'typeof' || op === 'delete') || (op === '+' || op === '-') && op === code.join("").charAt()) {
          op += ' ';
        }
        code.unshift(op);
      }
      if (o.level < LEVEL_CALL) {
        return sn.apply(null, [this].concat(slice$.call(code)));
      } else {
        return sn.apply(null, [this, "("].concat(slice$.call(code), [")"]));
      }
    };
    Unary.prototype.compileSpread = function(o) {
      var it,
          ops;
      it = this.it;
      ops = [this];
      for (; it instanceof constructor; it = it.it) {
        ops.push(it);
      }
      if (!(it instanceof Splat && (it = it.it.expandSlice(o).unwrap()) instanceof List)) {
        return '';
      }
      return this.compileSpreadOver(o, it, function(node) {
        var i$,
            ref$,
            op;
        for (i$ = (ref$ = ops).length - 1; i$ >= 0; --i$) {
          op = ref$[i$];
          node = constructor(op.op, node, op.post);
        }
        return node;
      });
    };
    Unary.prototype.compilePluck = function(o) {
      var ref$,
          get,
          del,
          code,
          ref;
      ref$ = Chain(this.it).cacheReference(o), get = ref$[0], del = ref$[1];
      code = [ref = o.scope.temporary(), " = ", get.compile(o, LEVEL_LIST), ", delete ", del.compile(o, LEVEL_LIST), ", ", o.scope.free(ref)];
      if (o.level < LEVEL_LIST) {
        return sn.apply(null, [this].concat(slice$.call(code)));
      } else {
        return sn.apply(null, [this, "("].concat(slice$.call(code), [")"]));
      }
    };
    Unary.prototype.compileAsFunc = function(o) {
      if (this.op === '!') {
        return sn(this, util('not'));
      } else {
        return sn(this, "(", Fun([], Block(Unary(this.op, Chain(Var('it'))))).compile(o), ")");
      }
    };
    return Unary;
  }(Node));
  exports.Binary = Binary = (function(superclass) {
    var COMPARER,
        INVERSIONS,
        prototype = extend$((import$(Binary, superclass).displayName = 'Binary', Binary), superclass).prototype,
        constructor = Binary;
    function Binary(op, first, second, destructuring) {
      var logic,
          that,
          ref$,
          this$ = this instanceof ctor$ ? this : new ctor$;
      if (destructuring) {
        logic = op.logic;
        if (toString$.call(destructuring).slice(8, -1) === 'String') {
          logic = destructuring;
        }
        op = (function() {
          switch (false) {
            case !(that = logic):
              return that;
            case op !== '=':
              return '?';
            default:
              return '=';
          }
        }());
      }
      this$.partial = first == null || second == null;
      if (!this$.partial) {
        if ('=' === op.charAt(op.length - 1) && ((ref$ = op.charAt(op.length - 2)) !== '=' && ref$ !== '<' && ref$ !== '>' && ref$ !== '!')) {
          return Assign(first.unwrap(), second, op);
        }
        switch (op) {
          case 'in':
            return new In(first, second);
          case 'with':
            return new Import(Unary('^^', first), second, false);
          case '<<<':
          case '<<<<':
            return Import(first, second, op === '<<<<');
          case '<|':
            return Block(first).pipe(second, op);
          case '|>':
            return Block(second).pipe(first, '<|');
          case '.':
          case '.~':
            return Chain(first).add(Index(second, op));
        }
      }
      this$.op = op;
      this$.first = first;
      this$.second = second;
      return this$;
    }
    function ctor$() {}
    ctor$.prototype = prototype;
    Binary.prototype.children = ['first', 'second'];
    Binary.prototype.show = function() {
      return this.op;
    };
    Binary.prototype.isCallable = function() {
      var ref$;
      return this.partial || ((ref$ = this.op) === '&&' || ref$ === '||' || ref$ === '?' || ref$ === '<<' || ref$ === '>>') && this.first.isCallable() && this.second.isCallable();
    };
    Binary.prototype.isArray = function() {
      switch (this.op) {
        case '*':
          return this.first.isArray();
        case '/':
          return this.second.isMatcher();
      }
    };
    Binary.prototype.isString = function() {
      switch (this.op) {
        case '+':
        case '*':
          return this.first.isString() || this.second.isString();
        case '-':
          return this.second.isMatcher();
      }
    };
    COMPARER = /^(?:[!=]=|[<>])=?$/;
    INVERSIONS = {
      '===': '!==',
      '!==': '===',
      '==': '!=',
      '!=': '=='
    };
    Binary.prototype.invert = function() {
      var that;
      if (that = !COMPARER.test(this.second.op) && INVERSIONS[this.op]) {
        this.op = that;
        this.wasInverted = true;
        return this;
      }
      return Unary('!', Parens(this), true);
    };
    Binary.prototype.invertIt = function() {
      this.inverted = true;
      return this;
    };
    Binary.prototype.getDefault = function() {
      switch (this.op) {
        case '?':
        case '||':
        case '&&':
          return this;
      }
    };
    Binary.prototype.xorChildren = function(test) {
      var ref$,
          ref1$,
          first;
      if (!(!(ref$ = first = test(this.first)) !== !(ref1$ = test(this.second)) && (ref$ || ref1$))) {
        return false;
      }
      return first ? [this.first, this.second] : [this.second, this.first];
    };
    Binary.prototype.compileNode = function(o) {
      var top,
          rite,
          items,
          that,
          ref$,
          code,
          level,
          this$ = this;
      if (this.partial) {
        return this.compilePartial(o);
      }
      switch (this.op) {
        case '?':
          return this.compileExistence(o);
        case '*':
          if (this.second.isString()) {
            return this.compileJoin(o);
          }
          if (this.first.isString() || this.first.isArray()) {
            return this.compileRepeat(o);
          }
          break;
        case '-':
          if (this.second.isMatcher()) {
            return this.compileRemove(o);
          }
          break;
        case '/':
          if (this.second.isMatcher()) {
            return this.compileSplit(o);
          }
          break;
        case '**':
        case '^':
          return this.compilePow(o);
        case '<?':
        case '>?':
          return this.compileMinMax(o);
        case '<<':
        case '>>':
          return this.compileCompose(o);
        case '++':
          return this.compileConcat(o);
        case '%%':
          return this.compileMod(o);
        case 'xor':
          return this.compileXor(o);
        case '&&':
        case '||':
          if (top = this['void'] || !o.level) {
            this.second['void'] = true;
          }
          if (top || this.cond) {
            this.first.cond = true;
            this.second.cond = true;
          }
          break;
        case 'instanceof':
          rite = this.second.expandSlice(o).unwrap(), items = rite.items;
          if (rite instanceof Arr) {
            if (items[1]) {
              return this.compileAnyInstanceOf(o, items);
            }
            this.second = items[0] || rite;
          }
          this.second.isCallable() || this.second.carp('invalid instanceof operand');
          break;
        case '====':
        case '!===':
          this.op = this.op.slice(0, 3);
        case '<==':
        case '>==':
        case '<<=':
        case '>>=':
          return this.compileDeepEq(o);
        default:
          if (COMPARER.test(this.op)) {
            if (that = ((ref$ = this.op) === '===' || ref$ === '!==') && this.xorChildren(function(it) {
              return it.isRegex();
            })) {
              return this.compileRegexEquals(o, that);
            }
            if (this.op === '===' && (this.first instanceof Literal && this.second instanceof Literal) && this.first.isWhat() !== this.second.isWhat()) {
              if (typeof console != 'undefined' && console !== null) {
                console.warn("WARNING: strict comparison of two different types will always be false: " + this.first.value + " == " + this.second.value);
              }
            }
          }
          if (COMPARER.test(this.op) && COMPARER.test(this.second.op)) {
            return this.compileChain(o);
          }
      }
      this.first.front = this.front;
      code = [this.first.compile(o, level = LEVEL_OP + PREC[this.op]), " ", this.mapOp(this.op), " ", this.second.compile(o, level)];
      if (o.level <= level) {
        return sn.apply(null, [this].concat(slice$.call(code)));
      } else {
        return sn.apply(null, [this, "("].concat(slice$.call(code), [")"]));
      }
    };
    Binary.prototype.mapOp = function(op) {
      var that;
      switch (false) {
        case !(that = op.match(/\.([&\|\^]|<<|>>>?)\./)):
          return that[1];
        case op !== 'of':
          return 'in';
        default:
          return op;
      }
    };
    Binary.prototype.compileChain = function(o) {
      var code,
          level,
          ref$,
          sub;
      code = [this.first.compile(o, level = LEVEL_OP + PREC[this.op])];
      ref$ = this.second.first.cache(o, true), sub = ref$[0], this.second.first = ref$[1];
      code.push(" ", this.op, " ", sub.compile(o, level), " && ", this.second.compile(o, LEVEL_OP));
      if (o.level <= LEVEL_OP) {
        return sn.apply(null, [this].concat(slice$.call(code)));
      } else {
        return sn.apply(null, [this, "("].concat(slice$.call(code), [")"]));
      }
    };
    Binary.prototype.compileExistence = function(o) {
      var x;
      if (this['void'] || !o.level) {
        x = Binary('&&', Existence(this.first, true), this.second);
        return (x['void'] = true, x).compileNode(o);
      }
      x = this.first.cache(o, true);
      return sn(this, If(Existence(x[0]), x[1]).addElse(this.second).compileExpression(o));
    };
    Binary.prototype.compileAnyInstanceOf = function(o, items) {
      var ref$,
          sub,
          ref,
          test,
          i$,
          len$,
          item;
      ref$ = this.first.cache(o), sub = ref$[0], ref = ref$[1], this.temps = ref$[2];
      test = Binary('instanceof', sub, items.shift());
      for (i$ = 0, len$ = items.length; i$ < len$; ++i$) {
        item = items[i$];
        test = Binary('||', test, Binary('instanceof', ref, item));
      }
      return sn(this, Parens(test).compile(o));
    };
    Binary.prototype.compileMinMax = function(o) {
      var lefts,
          rites,
          x;
      lefts = this.first.cache(o, true);
      rites = this.second.cache(o, true);
      x = Binary(this.op.charAt(), lefts[0], rites[0]);
      return sn(this, If(x, lefts[1]).addElse(rites[1]).compileExpression(o));
    };
    Binary.prototype.compileMethod = function(o, klass, method, arg) {
      var args;
      args = [this.second].concat(arg || []);
      if (this.first["is" + klass]()) {
        return sn(this, Chain(this.first, [Index(Key(method)), Call(args)]).compile(o));
      } else {
        args.unshift(this.first);
        return sn(this, Call.make(JS(util(method) + '.call'), args).compile(o));
      }
    };
    Binary.prototype.compileJoin = function(it) {
      return this.compileMethod(it, 'Array', 'join');
    };
    Binary.prototype.compileRemove = function(it) {
      return this.compileMethod(it, 'String', 'replace', JS("''"));
    };
    Binary.prototype.compileSplit = function(it) {
      return this.compileMethod(it, 'String', 'split');
    };
    Binary.prototype.compileRepeat = function(o) {
      var x,
          n,
          items,
          arr,
          arrCode,
          refs,
          i$,
          len$,
          i,
          item,
          ref$,
          q;
      x = this.first, n = this.second;
      items = (x = x.expandSlice(o).unwrap()).items;
      arr = x.isArray() && 'Array';
      if (items && !snEmpty(arrCode = Splat.compileArray(o, items))) {
        x = JS(arrCode);
        items = null;
      }
      if (arr && !items || !(n instanceof Literal && n.value < 0x20)) {
        return sn(this, Call.make(Util('repeat' + (arr || 'String')), [x, n]).compile(o));
      }
      n = +n.value;
      if (1 <= n && n < 2) {
        return sn(this, x.compile(o));
      }
      if (items) {
        if (n < 1) {
          return sn(this, Block(items).add(JS('[]')).compile(o));
        }
        refs = [];
        for (i$ = 0, len$ = items.length; i$ < len$; ++i$) {
          i = i$;
          item = items[i$];
          ref$ = item.cache(o, 1), items[i] = ref$[0], refs[refs.length] = ref$[1];
        }
        items.push((ref$ = JS(), ref$.compile = function() {
          return sn.apply(null, [this].concat(slice$.call((repeatArray$([", ", List.compile(o, refs)], n - 1)).slice(1))));
        }, ref$));
        return sn(this, x.compile(o));
      } else if (x instanceof Literal) {
        return sn(this, (q = (x = x.compile(o).toString()).charAt()) + repeatString$(x.slice(1, -1) + "", n) + q);
      } else {
        if (n < 1) {
          return sn(this, Block(x.it).add(JS("''")).compile(o));
        }
        x = (refs = x.cache(o, 1, LEVEL_OP))[0] + repeatString$(" + " + refs[1], n - 1);
        if (o.level < LEVEL_OP + PREC['+']) {
          return sn(this, x);
        } else {
          return sn(this, "(", x, ")");
        }
      }
    };
    Binary.prototype.compilePow = function(o) {
      return sn(null, Call.make(CopyL(this, JS('Math.pow')), [this.first, this.second]).compile(o));
    };
    Binary.prototype.compileConcat = function(o) {
      var f;
      f = function(x) {
        switch (false) {
          case !(x instanceof Binary && x.op === '++'):
            return f(x.first).concat(f(x.second));
          default:
            return [x];
        }
      };
      return sn(null, Chain(this.first).add(CopyL(this, Index(Key('concat'), '.', true))).add(Call(f(this.second))).compile(o));
    };
    Binary.prototype.compileCompose = function(o) {
      var op,
          functions,
          x;
      op = this.op;
      functions = [this.first];
      x = this.second;
      while (x instanceof Binary && x.op === op && !x.partial) {
        functions.push(x.first);
        x = x.second;
      }
      functions.push(x);
      if (op === '<<') {
        functions.reverse();
      }
      return sn(this, Chain(Var(util('compose'))).add(Call(functions)).compile(o));
    };
    Binary.prototype.compileMod = function(o) {
      var ref,
          code;
      ref = o.scope.temporary();
      code = [sn(this, "((("), this.first.compile(o), sn(this, ") % ("), sn(this, ref, " = "), this.second.compile(o), sn(this, ") + ", ref, ") % ", ref, ")")];
      o.scope.free(ref);
      return sn.apply(null, [null].concat(slice$.call(code)));
    };
    Binary.prototype.compilePartial = function(o) {
      var vit,
          x,
          y;
      vit = Var('it');
      switch (false) {
        case !(this.first == null && this.second == null):
          x = Var('x$');
          y = Var('y$');
          return sn(this, Fun([x, y], Block(Binary(this.op, x, y).invertCheck(this)), false, true).compile(o));
        case this.first == null:
          return sn(this, "(", Fun([vit], Block(Binary(this.op, this.first, vit).invertCheck(this)), true).compile(o), ")");
        default:
          return sn(this, "(", Fun([vit], Block(Binary(this.op, vit, this.second).invertCheck(this)), true).compile(o), ")");
      }
    };
    Binary.prototype.compileRegexEquals = function(o, arg$) {
      var regex,
          target,
          method;
      regex = arg$[0], target = arg$[1];
      if (this.op === '===') {
        method = this.wasInverted ? 'test' : 'exec';
        return sn(this, Chain(regex).add(Index(Key(method))).add(Call([target])).compile(o));
      } else {
        return sn(this, Unary('!', Chain(regex).add(Index(Key('test'))).add(Call([target]))).compile(o));
      }
    };
    Binary.prototype.compileDeepEq = function(o) {
      var ref$,
          negate,
          i$,
          len$,
          x,
          r;
      if ((ref$ = this.op) === '>==' || ref$ === '>>=') {
        ref$ = [this.second, this.first], this.first = ref$[0], this.second = ref$[1];
        this.op = this.op === '>==' ? '<==' : '<<=';
      }
      if (this.op === '!==') {
        this.op = '===';
        negate = true;
      }
      for (i$ = 0, len$ = (ref$ = [this.first, this.second]).length; i$ < len$; ++i$) {
        x = ref$[i$];
        if (x instanceof Obj || x instanceof Arr) {
          x.deepEq = true;
        }
      }
      r = Chain(Var(util('deepEq'))).add(Call([this.first, this.second, Literal("'" + this.op + "'")]));
      return sn(this, (negate ? Unary('!', r) : r).compile(o));
    };
    Binary.prototype.compileXor = function(o) {
      var left,
          right;
      left = Chain(this.first).cacheReference(o);
      right = Chain(this.second).cacheReference(o);
      return sn(this, Binary('&&', Binary('!==', Unary('!', left[0]), Unary('!', right[0])), Parens(Binary('||', left[1], right[1]))).compile(o));
    };
    return Binary;
  }(Node));
  exports.Assign = Assign = (function(superclass) {
    var prototype = extend$((import$(Assign, superclass).displayName = 'Assign', Assign), superclass).prototype,
        constructor = Assign;
    function Assign(left, rite, op, logic, defParam) {
      var this$ = this instanceof ctor$ ? this : new ctor$;
      this$.left = left;
      this$.op = op || '=';
      this$.logic = logic || this$.op.logic;
      this$.defParam = defParam;
      this$.opLoc = this$.op;
      this$.op += '';
      this$[rite instanceof Node ? 'right' : 'unaries'] = rite;
      return this$;
    }
    function ctor$() {}
    ctor$.prototype = prototype;
    Assign.prototype.children = ['left', 'right'];
    Assign.prototype.show = function() {
      return [void 8].concat(this.unaries).reverse().join(' ') + [this.logic] + this.op;
    };
    Assign.prototype.assigns = function(it) {
      return this.left.assigns(it);
    };
    prototype.delegate(['isCallable', 'isRegex'], function(it) {
      var ref$;
      return ((ref$ = this.op) === '=' || ref$ === ':=') && this.right && this.right[it]();
    });
    Assign.prototype.isArray = function() {
      switch (this.op) {
        case '=':
        case ':=':
          return this.right && this.right.isArray();
        case '/=':
          return this.right && this.right.isMatcher();
      }
    };
    Assign.prototype.isString = function() {
      switch (this.op) {
        case '=':
        case ':=':
        case '+=':
        case '*=':
          return this.right && this.right.isString();
        case '-=':
          return this.right && this.right.isMatcher();
      }
    };
    Assign.prototype.unfoldSoak = function(o) {
      var that,
          ref$,
          ref1$,
          rite,
          temps;
      if (this.left instanceof Existence) {
        if (that = (ref1$ = (ref$ = this.left = this.left.it).name, delete ref$.name, ref1$)) {
          rite = this.right;
          rite = Assign(this.right = Var(that), rite);
        } else {
          ref$ = this.right.cache(o), rite = ref$[0], this.right = ref$[1], temps = ref$[2];
        }
        return ref$ = If(Existence(rite), this), ref$.temps = temps, ref$.cond = this.cond, ref$['void'] = this['void'], ref$;
      }
      return If.unfoldSoak(o, this, 'left');
    };
    Assign.prototype.unfoldAssign = function() {
      return this.access && this;
    };
    Assign.prototype.compileNode = function(o) {
      var left,
          sp,
          ref$,
          i$,
          len$,
          op,
          right,
          reft,
          sign,
          name,
          lvar,
          that,
          protoSplit,
          dotSplit,
          code,
          empty,
          res;
      if (this.left instanceof Slice && this.op === '=') {
        return this.compileSplice(o);
      }
      left = this.left;
      if (sp = this.left instanceof Splat) {
        left = left.it;
      }
      left = left.expandSlice(o, true).unwrap();
      if (sp) {
        left instanceof List || this.left.carp('invalid splat');
        return this.compileSpread(o, left);
      }
      if (!this.right) {
        left.isAssignable() || left.carp('invalid unary assign');
        ref$ = Chain(left).cacheReference(o), left = ref$[0], this.right = ref$[1];
        for (i$ = 0, len$ = (ref$ = this.unaries).length; i$ < len$; ++i$) {
          op = ref$[i$];
          this.right = Unary(op, this.right);
        }
      }
      if (left.isEmpty()) {
        return sn(null, (ref$ = Parens(this.right), ref$.front = this.front, ref$.newed = this.newed, ref$).compile(o));
      }
      if (left.getDefault()) {
        this.right = Binary(left.op, this.right, left.second);
        left = left.first;
      }
      if (left.items) {
        return this.compileDestructuring(o, left);
      }
      left.isAssignable() || left.carp('invalid assign');
      if (this.logic) {
        return this.compileConditional(o, left);
      }
      op = this.op, right = this.right;
      if (op === '<?=' || op === '>?=') {
        return this.compileMinMax(o, left, right);
      }
      if ((op === '**=' || op === '^=' || op === '%%=' || op === '++=' || op === '|>=') || op === '*=' && right.isString() || (op === '-=' || op === '/=') && right.isMatcher()) {
        ref$ = Chain(left).cacheReference(o), left = ref$[0], reft = ref$[1];
        right = Binary(op.slice(0, -1), reft, right);
        op = ':=';
      }
      if (op === '.&.=' || op === '.|.=' || op === '.^.=' || op === '.<<.=' || op === '.>>.=' || op === '.>>>.=') {
        op = op.slice(1, -2) + '=';
      }
      (right = right.unparen()).ripName(left = left.unwrap());
      sign = sn(this.opLoc, " ", op.replace(':', ''), " ");
      name = (left.front = true, left).compile(o, LEVEL_LIST);
      if (lvar = left instanceof Var) {
        if (op === '=') {
          o.scope.declare(name.toString(), left, this['const'] || !this.defParam && o['const'] && '$' !== name.toString().slice(-1));
        } else if (that = o.scope.checkReadOnly(name.toString())) {
          left.carp("assignment to " + that + " \"" + name + "\"", ReferenceError);
        }
      }
      if (left instanceof Chain && right instanceof Fun) {
        protoSplit = name.toString().split('.prototype.');
        dotSplit = name.toString().split('.');
        if (protoSplit.length > 1) {
          right.inClass = protoSplit[0];
        } else if (dotSplit.length > 1) {
          right.inClassStatic = slice$.call(dotSplit, 0, -1).join('');
        }
      }
      code = !o.level && right instanceof While && !right['else'] && (lvar || left instanceof Chain && left.isSimpleAccess()) ? (empty = right.objComp ? '{}' : '[]', [res = o.scope.temporary('res'), " = " + empty + ";\n" + this.tab, right.makeReturn(res).compile(o), "\n" + this.tab, name, sign, o.scope.free(res)]) : [name, sign, right.compile(o, LEVEL_LIST)];
      if (o.level > LEVEL_LIST) {
        code = ["("].concat(slice$.call(code), [")"]);
      }
      return sn.apply(null, [null].concat(slice$.call(code)));
    };
    Assign.prototype.compileConditional = function(o, left) {
      var lefts,
          morph;
      if (left instanceof Var && in$(this.logic, ['?']) && this.op === '=') {
        o.scope.declare(left.value, left);
      }
      lefts = Chain(left).cacheReference(o);
      o.level += LEVEL_OP < o.level;
      morph = Binary(this.logic, lefts[0], (this.logic = false, this.left = lefts[1], this));
      return sn(this, (morph['void'] = this['void'], morph).compileNode(o));
    };
    Assign.prototype.compileMinMax = function(o, left, right) {
      var lefts,
          rites,
          test,
          put,
          ref$;
      lefts = Chain(left).cacheReference(o);
      rites = right.cache(o, true);
      test = Binary(this.op.replace('?', ''), lefts[0], rites[0]);
      put = Assign(lefts[1], rites[1], ':=');
      if (this['void'] || !o.level) {
        return Parens(Binary('||', test, put)).compile(o);
      }
      ref$ = test.first.cache(o, true), test.first = ref$[0], left = ref$[1];
      return sn(this, If(test, left).addElse(put).compileExpression(o));
    };
    Assign.prototype.compileDestructuring = function(o, left) {
      var items,
          len,
          ret,
          rite,
          that,
          cache,
          rref,
          destructureArgs,
          list,
          code,
          sep,
          i$,
          len$,
          item;
      items = left.items, len = items.length;
      ret = o.level && !this['void'];
      rite = this.right.compile(o, len === 1 ? LEVEL_CALL : LEVEL_LIST);
      if (that = left.name) {
        cache = sn(this, that, " = ", rite);
        o.scope.declare(rite = that, left);
      } else if ((ret || len > 1) && (!ID.test(rite.toString()) || left.assigns(rite.toString()))) {
        cache = sn(this, rref = o.scope.temporary(), " = ", rite);
        rite = rref;
      }
      if (rite.toString() === 'arguments' && !ret) {
        destructureArgs = true;
        if (!(left instanceof Arr)) {
          this.carp('arguments can only destructure to array');
        }
      }
      list = this["rend" + left.constructor.displayName](o, items, rite, destructureArgs);
      if (rref) {
        o.scope.free(rref);
      }
      if (cache) {
        list.unshift(cache);
      }
      if (ret || !list.length) {
        list.push(rite);
      }
      code = [];
      sep = destructureArgs ? '; ' : ', ';
      for (i$ = 0, len$ = list.length; i$ < len$; ++i$) {
        item = list[i$];
        code.push(item, sep);
      }
      code.pop();
      if (list.length < 2 || o.level < LEVEL_LIST) {
        return sn.apply(null, [this].concat(slice$.call(code)));
      } else {
        return sn.apply(null, [this, "("].concat(slice$.call(code), [")"]));
      }
    };
    Assign.prototype.compileSplice = function(o) {
      var ref$,
          fromExpNode,
          fromExp,
          rightNode,
          right,
          toExp;
      ref$ = Chain(this.left.from).cacheReference(o), fromExpNode = ref$[0], fromExp = ref$[1];
      ref$ = Chain(this.right).cacheReference(o), rightNode = ref$[0], right = ref$[1];
      toExp = Binary('-', this.left.to, fromExp);
      return sn(this, Block([Chain(Var(util('splice'))).add(Index(Key('apply'), '.', true)).add(Call([this.left.target, Chain(Arr([fromExpNode, toExp])).add(Index(Key('concat'), '.', true)).add(Call([rightNode]))])), right]).compile(o, LEVEL_LIST));
    };
    Assign.prototype.compileSpread = function(o, left) {
      var that,
          ref$,
          rite,
          rref,
          this$ = this;
      ref$ = (that = this.unaries) ? [that, that] : left.items.length <= 1 ? [ref$ = this.right, ref$] : this.right.cache(o, true), rite = ref$[0], rref = ref$[1];
      return this.compileSpreadOver(o, left, function(it) {
        var result;
        result = constructor(it, rite, this$.op, this$.logic);
        rite = rref;
        return result;
      });
    };
    Assign.prototype.rendArr = function(o, nodes, rite, destructureArgs) {
      var ret,
          i$,
          len$,
          i,
          node,
          skip,
          len,
          val,
          ivar,
          start,
          inc,
          rcache,
          tmp,
          vtmp,
          ref$,
          this$ = this;
      function argsSlice(begin, end) {
        return new For({
          ref: true,
          from: begin,
          op: 'til',
          to: end
        }).makeComprehension(Chain(Var('arguments')).add(Index(Literal('..'))), []);
      }
      ret = [];
      for (i$ = 0, len$ = nodes.length; i$ < len$; ++i$) {
        i = i$;
        node = nodes[i$];
        if (node.isEmpty()) {
          continue;
        }
        if (node instanceof Splat) {
          len && node.carp('multiple splat in an assignment');
          skip = (node = node.it).isEmpty();
          if (i + 1 === (len = nodes.length)) {
            if (skip) {
              break;
            }
            if (destructureArgs) {
              val = argsSlice(Literal(i), Chain(Var('arguments')).add(Index(Key('length'))));
            } else {
              val = Arr.wrap(JS(util('slice') + '.call(' + rite + (i ? ", " + i + ")" : ')')));
            }
          } else {
            val = ivar = rite + ".length - " + (len - i - 1);
            if (skip && i + 2 === len) {
              continue;
            }
            start = i + 1;
            (this.temps || (this.temps = [])).push(ivar = o.scope.temporary('i'));
            val = (fn$());
          }
        } else {
          (inc = ivar) && start < i && (inc += " + " + (i - start));
          val = Chain(rcache || (rcache = Literal(rite)), [Index(JS(inc || i))]);
        }
        if (node instanceof Assign) {
          node = Binary(node.op, node.left, node.right, node.logic || true);
        }
        if (destructureArgs) {
          if (!(node instanceof Var) && val instanceof For) {
            (this.temps || (this.temps = [])).push(tmp = o.scope.temporary('ref'));
            vtmp = Var(tmp);
            ret.push((ref$ = clone$(this), ref$.left = vtmp, ref$.right = val, ref$['void'] = true, ref$).compile(o, LEVEL_TOP));
            ret.push((ref$ = clone$(this), ref$.left = node, ref$.right = vtmp, ref$['void'] = true, ref$).compile(o, LEVEL_TOP));
          } else {
            ret.push((ref$ = clone$(this), ref$.left = node, ref$.right = val, ref$['void'] = true, ref$).compile(o, LEVEL_TOP));
          }
        } else {
          ret.push((ref$ = clone$(this), ref$.left = node, ref$.right = val, ref$['void'] = true, ref$).compile(o, LEVEL_PAREN));
        }
      }
      return ret;
      function fn$() {
        switch (false) {
          case !skip:
            return Arr.wrap(JS(i + " < (" + ivar + " = " + val + ") ? " + i + " : (" + ivar + " = " + i + ")"));
          case !destructureArgs:
            return argsSlice(JS(i + " < (" + ivar + " = " + val + ") ? " + i + " : (" + ivar + " = " + i + ")"), Var(ivar));
          default:
            return Arr.wrap(JS(i + " < (" + ivar + " = " + val + ")\ ? " + util('slice') + ".call(" + rite + ", " + i + ", " + ivar + ")\ : (" + ivar + " = " + i + ", [])"));
        }
      }
    };
    Assign.prototype.rendObj = function(o, nodes, rite) {
      var i$,
          len$,
          node,
          splat,
          logic,
          ref$,
          key,
          val,
          rcache,
          results$ = [];
      for (i$ = 0, len$ = nodes.length; i$ < len$; ++i$) {
        node = nodes[i$];
        if (splat = node instanceof Splat) {
          node = node.it;
        }
        if (logic = node.getDefault()) {
          node = node.first;
        }
        if (node instanceof Parens) {
          ref$ = Chain(node.it).cacheReference(o), node = ref$[0], key = ref$[1];
        } else if (node instanceof Prop) {
          node = (key = node.key, node).val;
        } else {
          key = node;
        }
        if (node instanceof Key) {
          node = CopyL(node, Var(node.name));
        }
        if (logic) {
          node = (logic.first = node, logic);
        }
        val = Chain(rcache || (rcache = Var(rite)), [Index(key.maybeKey())]);
        if (splat) {
          val = Import(Obj(), val);
        }
        results$.push((ref$ = clone$(this), ref$.left = node, ref$.right = val, ref$['void'] = true, ref$).compile(o, LEVEL_PAREN));
      }
      return results$;
    };
    return Assign;
  }(Node));
  exports.Import = Import = (function(superclass) {
    var prototype = extend$((import$(Import, superclass).displayName = 'Import', Import), superclass).prototype,
        constructor = Import;
    function Import(left, right, all) {
      var this$ = this instanceof ctor$ ? this : new ctor$;
      this$.left = left;
      this$.right = right;
      this$.all = all && 'All';
      if (!all && left instanceof Obj && right.items) {
        return Obj(left.items.concat(right.asObj().items));
      }
      return this$;
    }
    function ctor$() {}
    ctor$.prototype = prototype;
    Import.prototype.children = ['left', 'right'];
    Import.prototype.show = function() {
      return this.all;
    };
    prototype.delegate(['isCallable', 'isArray'], function(it) {
      return this.left[it]();
    });
    Import.prototype.unfoldSoak = function(o) {
      var left,
          value,
          ref$,
          temps;
      left = this.left;
      if (left instanceof Existence && !left.negated) {
        if ((left = left.it) instanceof Var) {
          value = (this.left = left).value;
          if (!o.scope.check(value, true)) {
            left = JS("typeof " + value + " != 'undefined' && " + value);
          }
        } else {
          ref$ = left.cache(o), left = ref$[0], this.left = ref$[1], temps = ref$[2];
        }
        return ref$ = If(left, this), ref$.temps = temps, ref$.soak = true, ref$.cond = this.cond, ref$['void'] = this['void'], ref$;
      }
      return If.unfoldSoak(o, this, 'left') || (this['void'] || !o.level) && If.unfoldSoak(o, this, 'right');
    };
    Import.prototype.compileNode = function(o) {
      var right;
      right = this.right;
      if (!this.all) {
        if (right instanceof Chain) {
          right = right.unfoldSoak(o) || right.unfoldAssign(o) || right.expandSlice(o).unwrap();
        }
        if (right instanceof List) {
          return this.compileAssign(o, right.asObj().items);
        }
      }
      return CopyL(this, Call.make(Util("import" + (this.all || '')), [this.left, right])).compileNode(o);
    };
    Import.prototype.compileAssign = function(o, items) {
      var top,
          reft,
          ref$,
          left,
          delim,
          space,
          code,
          i$,
          len$,
          i,
          node,
          com,
          logic,
          dyna,
          key,
          val;
      if (!items.length) {
        return this.left.compile(o);
      }
      top = !o.level;
      if (this.proto || (items.length < 2 && (top || this['void'] || items[0] instanceof Splat))) {
        reft = this.left;
        if (reft.isComplex()) {
          reft = Parens(reft);
        }
      } else {
        ref$ = this.left.cache(o), left = ref$[0], reft = ref$[1], this.temps = ref$[2];
      }
      ref$ = top ? [';', '\n' + this.tab] : [',', ' '], delim = ref$[0], space = ref$[1];
      delim += space;
      code = this.temps ? [left.compile(o, LEVEL_PAREN), delim] : [];
      for (i$ = 0, len$ = items.length; i$ < len$; ++i$) {
        i = i$;
        node = items[i$];
        i && code.push(com ? space : delim);
        if (com = node.comment) {
          code.push(node.compile(o));
          continue;
        }
        if (node instanceof Splat) {
          code.push(Import(reft, node.it).compile(o));
          continue;
        }
        if (logic = node.getDefault()) {
          node = node.first;
        }
        if (dyna = node instanceof Parens) {
          ref$ = node.it.cache(o, true), key = ref$[0], val = ref$[1];
        } else if (node instanceof Prop) {
          key = node.key, val = node.val;
          if (node.accessor) {
            if (key instanceof Key) {
              key = JS("'" + key.name + "'");
            }
            code.push("Object.defineProperty(", reft.compile(o, LEVEL_LIST), ", ", key.compile(o, LEVEL_LIST), ", ", node.compileDescriptor(o), ")");
            continue;
          }
        } else {
          key = val = node;
        }
        dyna || (key = key.maybeKey());
        logic && (val = (logic.first = val, logic));
        code.push(Assign(Chain(reft, [Index(key)]), val).compile(o, LEVEL_PAREN));
      }
      if (top) {
        return sn.apply(null, [null].concat(slice$.call(code)));
      }
      this['void'] || node instanceof Splat || code.push(com ? ' ' : ', ', reft.compile(o, LEVEL_PAREN));
      if (o.level < LEVEL_LIST) {
        return sn.apply(null, [null].concat(slice$.call(code)));
      } else {
        return sn.apply(null, [null, "("].concat(slice$.call(code), [")"]));
      }
    };
    return Import;
  }(Node));
  exports.In = In = (function(superclass) {
    var prototype = extend$((import$(In, superclass).displayName = 'In', In), superclass).prototype,
        constructor = In;
    importAll$(prototype, arguments[1]);
    function In(item, array) {
      this.item = item;
      this.array = array;
    }
    In.prototype.children = ['item', 'array'];
    In.prototype.compileNode = function(o) {
      var array,
          items,
          code,
          ref$,
          sub,
          ref,
          cmp,
          cnj,
          i$,
          len$,
          i,
          test;
      items = (array = this.array.expandSlice(o).unwrap()).items;
      if (!(array instanceof Arr) || items.length < 2) {
        return sn(this, this.negated ? '!' : '', util('in'), "(", this.item.compile(o, LEVEL_LIST), ", ", array.compile(o, LEVEL_LIST), ")");
      }
      code = [];
      ref$ = this.item.cache(o, false, LEVEL_PAREN), sub = ref$[0], ref = ref$[1];
      ref$ = this.negated ? [' !== ', ' && '] : [' === ', ' || '], cmp = ref$[0], cnj = ref$[1];
      for (i$ = 0, len$ = items.length; i$ < len$; ++i$) {
        i = i$;
        test = items[i$];
        if (code.length > 0) {
          code.push(cnj);
        }
        if (test instanceof Splat) {
          code.push((ref$ = new In(Var(ref), test.it), ref$.negated = this.negated, ref$).compile(o, LEVEL_TOP));
          if (!(i || sub === ref)) {
            code = ["(" + sub + ", "].concat(slice$.call(code), [")"]);
          }
        } else {
          code.push(i || sub === ref ? ref : "(" + sub + ")", cmp, test.compile(o, LEVEL_OP + PREC['==']));
        }
      }
      sub === ref || o.scope.free(ref);
      if (o.level < LEVEL_OP + PREC['||']) {
        return sn.apply(null, [this].concat(slice$.call(code)));
      } else {
        return sn.apply(null, [this, "("].concat(slice$.call(code), [")"]));
      }
    };
    return In;
  }(Node, Negatable));
  exports.Existence = Existence = (function(superclass) {
    var prototype = extend$((import$(Existence, superclass).displayName = 'Existence', Existence), superclass).prototype,
        constructor = Existence;
    importAll$(prototype, arguments[1]);
    function Existence(it, negated) {
      var this$ = this instanceof ctor$ ? this : new ctor$;
      this$.it = it;
      this$.negated = negated;
      return this$;
    }
    function ctor$() {}
    ctor$.prototype = prototype;
    Existence.prototype.children = ['it'];
    Existence.prototype.compileNode = function(o) {
      var node,
          ref$,
          code,
          op,
          eq;
      node = (ref$ = this.it.unwrap(), ref$.front = this.front, ref$);
      code = [node.compile(o, LEVEL_OP + PREC['=='])];
      if (node instanceof Var && !o.scope.check(code.join(""), true)) {
        ref$ = this.negated ? ['||', '='] : ['&&', '!'], op = ref$[0], eq = ref$[1];
        code = ["typeof "].concat(slice$.call(code), [" " + eq + "= 'undefined' " + op + " "], slice$.call(code), [" " + eq + "== null"]);
      } else {
        code.push(" " + (op = this.negated ? '==' : '!=') + " null");
      }
      if (o.level < LEVEL_OP + PREC[op]) {
        return sn.apply(null, [this].concat(slice$.call(code)));
      } else {
        return sn(this, "(", code, ")");
      }
    };
    return Existence;
  }(Node, Negatable));
  exports.Fun = Fun = (function(superclass) {
    var prototype = extend$((import$(Fun, superclass).displayName = 'Fun', Fun), superclass).prototype,
        constructor = Fun;
    function Fun(params, body, bound, curried, hushed, generator) {
      var this$ = this instanceof ctor$ ? this : new ctor$;
      this$.params = params || [];
      this$.body = body || Block();
      this$.bound = bound && 'this$';
      this$.curried = curried || false;
      this$.hushed = hushed != null ? hushed : false;
      this$.generator = generator != null ? generator : false;
      return this$;
    }
    function ctor$() {}
    ctor$.prototype = prototype;
    Fun.prototype.children = ['params', 'body'];
    Fun.prototype.show = function() {
      var that;
      return [this.name] + [(that = this.bound) ? "~" + that : void 8];
    };
    Fun.prototype.named = function(it) {
      return this.name = it, this.statement = true, this;
    };
    Fun.prototype.isCallable = YES;
    Fun.prototype.isStatement = function() {
      return !!this.statement;
    };
    Fun.prototype.traverseChildren = function(arg$, xscope) {
      if (xscope) {
        return superclass.prototype.traverseChildren.apply(this, arguments);
      }
    };
    Fun.prototype.makeReturn = function() {
      if (this.statement) {
        return this.returns = true, this;
      } else {
        return superclass.prototype.makeReturn.apply(this, arguments);
      }
    };
    Fun.prototype.ripName = function(it) {
      this.name || (this.name = it.varName());
    };
    Fun.prototype.compileNode = function(o) {
      var pscope,
          sscope,
          scope,
          that,
          inLoop,
          ref$,
          body,
          name,
          tab,
          code,
          bodyCode,
          curryCodeCheck,
          this$ = this;
      pscope = o.scope;
      sscope = pscope.shared || pscope;
      scope = o.scope = this.body.scope = new Scope(this.wrapper ? pscope : sscope, this.wrapper && sscope);
      scope.fun = this;
      if (that = this.proto) {
        scope.assign('prototype', that.compile(o) + ".prototype");
      }
      if (that = this.cname) {
        scope.assign('constructor', that);
      }
      if (inLoop = (ref$ = o.loop, delete o.loop, ref$)) {
        o.indent = this.tab = '';
      }
      o.indent += TAB;
      body = this.body, name = this.name, tab = this.tab;
      code = ['function'];
      if (this.generator) {
        this.ctor && this.carp("a constructor can't be a generator");
        o.inGenerator = true;
        code.push('*');
      } else if (!this.wrapper) {
        o.inGenerator = false;
      }
      if (this.bound === 'this$') {
        if (this.ctor) {
          scope.assign('this$', 'this instanceof ctor$ ? this : new ctor$');
          body.lines.push(Return(Literal('this$')));
        } else if (that = (ref$ = sscope.fun) != null ? ref$.bound : void 8) {
          this.bound = that;
        } else {
          sscope.assign('this$', 'this');
        }
      }
      if (this.statement) {
        name || this.carp('nameless function declaration');
        pscope === o.block.scope || this.carp('misplaced function declaration');
        this.accessor && this.carp('named accessor');
        pscope.add(name, 'function', this);
      }
      if (this.statement || name && this.labeled) {
        code.push(' ', scope.add(name, 'function', this));
      }
      this.hushed || this.ctor || this.newed || body.makeReturn();
      code.push("(", this.compileParams(o, scope), ")");
      code = [sn.apply(null, [this].concat(slice$.call(code)))];
      code.push("{");
      if (!snEmpty(bodyCode = body.compileWithDeclarations(o))) {
        code.push("\n", bodyCode, "\n" + tab);
      }
      code.push('}');
      curryCodeCheck = function() {
        if (this$.curried && this$.hasSplats) {
          this$.carp('cannot curry a function with a variable number of arguments');
        }
        if (this$.curried && this$.params.length > 1 && !this$.classBound) {
          if (this$.bound) {
            return [util('curry'), "(("].concat(slice$.call(code), ["), true)"]);
          } else {
            return [util('curry'), "("].concat(slice$.call(code), [")"]);
          }
        } else {
          return code;
        }
      };
      if (inLoop) {
        return pscope.assign(pscope.temporary('fn'), sn.apply(null, [null].concat(slice$.call(curryCodeCheck()))));
      }
      if (this.returns) {
        code.push("\n" + tab + "return ", name, ";");
      } else if (this.bound && this.ctor) {
        code.push(' function ctor$(){} ctor$.prototype = prototype;');
      }
      code = curryCodeCheck();
      if (this.front && !this.statement) {
        return sn.apply(null, [null, "("].concat(slice$.call(code), [")"]));
      } else {
        return sn.apply(null, [null].concat(slice$.call(code)));
      }
    };
    Fun.prototype.compileParams = function(o, scope) {
      var params,
          length,
          body,
          i$,
          p,
          len$,
          i,
          splace,
          rest,
          that,
          names,
          assigns,
          vr,
          df,
          unaries,
          hasUnary,
          v,
          ref$,
          ref1$;
      params = this.params, length = params.length, body = this.body;
      for (i$ = params.length - 1; i$ >= 0; --i$) {
        p = params[i$];
        if (!(p.isEmpty() || p.filler)) {
          break;
        }
        --params.length;
      }
      for (i$ = 0, len$ = params.length; i$ < len$; ++i$) {
        i = i$;
        p = params[i$];
        if (p.left instanceof Splat) {
          p.carp('invalid splat');
        }
        if (p instanceof Splat) {
          this.hasSplats = true;
          splace = i;
        } else if (p.op === '=') {
          params[i] = Binary(p.logic || '?', p.left, p.right);
        }
      }
      if (splace != null) {
        rest = params.splice(splace, 9e9);
      } else if (this.accessor) {
        if (that = params[1]) {
          that.carp('excess accessor parameter');
        }
      } else if (!(length || this.wrapper)) {
        if (body.traverseChildren(function(it) {
          return it.value === 'it' || null;
        })) {
          params[0] = Var('it');
        }
      }
      names = [];
      assigns = [];
      for (i$ = 0, len$ = params.length; i$ < len$; ++i$) {
        p = params[i$];
        vr = p;
        if (df = vr.getDefault()) {
          vr = vr.first;
        }
        if (vr.isEmpty()) {
          vr = Var(scope.temporary('arg'));
        } else if (vr.value === '..') {
          vr = Var(o.ref = scope.temporary());
        } else if (!(vr instanceof Var)) {
          unaries = [];
          while (vr instanceof Unary) {
            hasUnary = true;
            unaries.push(vr);
            vr = vr.it;
          }
          v = Var((ref1$ = (ref$ = vr.it || vr).name, delete ref$.name, ref1$) || vr.varName() || scope.temporary('arg'));
          assigns.push(Assign(vr, (fn$())));
          vr = v;
        } else if (df) {
          assigns.push(Assign(vr, p.second, '=', p.op, true));
        }
        names.push(scope.add(vr.value, 'arg', p), ', ');
      }
      if (rest) {
        while (splace--) {
          rest.unshift(Arr());
        }
        assigns.push(Assign(Arr(rest), Literal('arguments')));
      }
      if (assigns.length) {
        (ref$ = this.body).prepend.apply(ref$, assigns);
      }
      names.pop();
      return sn.apply(null, [null].concat(slice$.call(names)));
      function fn$() {
        switch (false) {
          case !df:
            return Binary(p.op, v, p.second);
          case !hasUnary:
            return fold(function(x, y) {
              y.it = x;
              return y;
            }, v, unaries.reverse());
          default:
            return v;
        }
      }
    };
    return Fun;
  }(Node));
  exports.Class = Class = (function(superclass) {
    var prototype = extend$((import$(Class, superclass).displayName = 'Class', Class), superclass).prototype,
        constructor = Class;
    function Class(arg$) {
      var body;
      this.title = arg$.title, this.sup = arg$.sup, this.mixins = arg$.mixins, body = arg$.body;
      this.fun = Fun([], body);
    }
    Class.prototype.children = ['title', 'sup', 'mixins', 'fun'];
    Class.prototype.isCallable = YES;
    Class.prototype.ripName = function(it) {
      this.name = it.varName();
    };
    Class.prototype.compile = function(o, level) {
      var fun,
          body,
          lines,
          title,
          boundFuncs,
          curriedBoundFuncs,
          decl,
          name,
          proto,
          vname,
          ctorName,
          ctor,
          ctorPlace,
          importProtoObj,
          i$,
          len$,
          i,
          node,
          f,
          args,
          that,
          imports,
          ref$,
          res$,
          clas;
      fun = this.fun, body = fun.body, lines = body.lines, title = this.title;
      CopyL(this, fun);
      boundFuncs = [];
      curriedBoundFuncs = [];
      decl = title != null ? title.varName() : void 8;
      name = decl || this.name;
      if (ID.test(name || '')) {
        fun.cname = name;
      } else {
        name = 'constructor';
      }
      proto = Var('prototype');
      vname = fun.proto = Var(fun.bound = name);
      ctorName = 'constructor$$';
      importProtoObj = function(node, i) {
        var j,
            prop,
            key,
            i$,
            ref$,
            len$,
            v;
        j = 0;
        for (; j < node.items.length; j++) {
          prop = node.items[j];
          key = prop.key;
          if ((key instanceof Key && key.name === ctorName) || (key instanceof Literal && key.value === "'" + ctorName + "'")) {
            if (ctor) {
              node.carp('redundant constructor');
            }
            ctor = prop.val;
            node.items.splice(j--, 1);
            ctorPlace = i;
          }
          if (!(prop.val instanceof Fun || prop.accessor)) {
            continue;
          }
          if (key.isComplex()) {
            key = Var(o.scope.temporary('key'));
            prop.key = Assign(key, prop.key);
          }
          if (prop.val.bound) {
            if (prop.val.curried) {
              curriedBoundFuncs.push(prop.key);
            } else {
              boundFuncs.push(prop.key);
            }
            prop.val.bound = false;
            prop.val.classBound = true;
          }
          for (i$ = 0, len$ = (ref$ = [].concat(prop.val)).length; i$ < len$; ++i$) {
            v = ref$[i$];
            v.meth = key;
          }
        }
        if (node.items.length) {
          return ref$ = Import(Chain(vname).add(Index(Key('prototype'))), node), ref$.proto = true, ref$;
        } else {
          return Literal('void');
        }
      };
      for (i$ = 0, len$ = lines.length; i$ < len$; ++i$) {
        i = i$;
        node = lines[i$];
        if (node instanceof Obj) {
          lines[i] = importProtoObj(node, i);
        } else if (node instanceof Fun && !node.statement) {
          ctor && node.carp('redundant constructor');
          ctor = node;
        } else if (node instanceof Assign && node.left instanceof Chain && node.left.head.value === 'this' && node.right instanceof Fun) {
          node.right.stat = node.left.tails[0].key;
        } else {
          node.traverseChildren(fn$);
        }
      }
      ctor || (ctor = lines[lines.length] = this.sup ? Fun([], Block(Chain(new Super).add(Call([Splat(Literal('arguments'))])))) : Fun());
      if (!(ctor instanceof Fun)) {
        lines.splice(ctorPlace + 1, 0, Assign(Var(ctorName), ctor));
        lines.unshift(ctor = Fun([], Block(Return(Chain(Var(ctorName)).add(Call([Splat('arguments', true)]))))));
      }
      ctor.name = name;
      ctor.ctor = true;
      ctor.statement = true;
      for (i$ = 0, len$ = boundFuncs.length; i$ < len$; ++i$) {
        f = boundFuncs[i$];
        ctor.body.lines.unshift(Assign(Chain(Literal('this')).add(Index(f)), Chain(Var(util('bind'))).add(Call([Literal('this'), Literal("'" + f.name + "'"), Var('prototype')]))));
      }
      for (i$ = 0, len$ = curriedBoundFuncs.length; i$ < len$; ++i$) {
        f = curriedBoundFuncs[i$];
        ctor.body.lines.unshift(Assign(Chain(Literal('this')).add(Index(Key("_" + f.name))), Chain(Var(util('curry'))).add(Call([Chain(Var('prototype')).add(Index(f)), Var('true')]))), Assign(Chain(Literal('this')).add(Index(f)), Chain(Var(util('bind'))).add(Call([Literal('this'), Literal("'_" + f.name + "'")]))));
      }
      lines.push(vname);
      args = [];
      if (that = this.sup) {
        args.push(that);
        imports = Chain(Import(Literal('this'), Var('superclass')));
        fun.proto = Util.Extends(fun.cname ? Block([Assign(imports.add(Index(Key('displayName'))), Literal("'" + name + "'")), Literal(name)]) : imports, (ref$ = fun.params)[ref$.length] = Var('superclass'));
      }
      if (that = this.mixins) {
        res$ = [];
        for (i$ = 0, len$ = that.length; i$ < len$; ++i$) {
          args[args.length] = that[i$];
          res$.push(Import(proto, JS("arguments[" + (args.length - 1) + "]"), true));
        }
        imports = res$;
        body.prepend.apply(body, imports);
      }
      if (fun.cname && !this.sup) {
        body.prepend(Literal(name + ".displayName = '" + name + "'"));
      }
      clas = Parens(Call.make(fun, args), true);
      if (decl && title.isComplex()) {
        clas = Assign(vname, clas);
      }
      if (title) {
        clas = Assign(title, clas);
      }
      return sn(null, clas.compile(o, level));
      function fn$(it) {
        var i$,
            ref$,
            len$,
            k,
            child;
        if (it instanceof Block) {
          for (i$ = 0, len$ = (ref$ = it.lines).length; i$ < len$; ++i$) {
            k = i$;
            child = ref$[i$];
            if (child instanceof Obj) {
              it.lines[k] = importProtoObj(child, i);
            }
          }
        }
      }
    };
    return Class;
  }(Node));
  exports.Super = Super = (function(superclass) {
    var prototype = extend$((import$(Super, superclass).displayName = 'Super', Super), superclass).prototype,
        constructor = Super;
    function Super() {}
    Super.prototype.isCallable = YES;
    Super.prototype.compile = function(o) {
      var scope,
          that,
          result,
          ref$;
      scope = o.scope;
      if (!this.sproto) {
        for (; that = !scope.get('superclass') && scope.fun; scope = scope.parent) {
          result = that;
          if (that = result.meth) {
            return sn(this, 'superclass.prototype', Index(that).compile(o));
          }
          if (that = result.stat) {
            return sn(this, 'superclass', Index(that).compile(o));
          }
          if (that = scope.fun.inClass) {
            return sn(this, that, ".superclass.prototype.", scope.fun.name);
          } else if (that = scope.fun.inClassStatic) {
            return sn(this, that, ".superclass.", scope.fun.name);
          }
        }
        if (that = (ref$ = o.scope.fun) != null ? ref$.name : void 8) {
          return sn(this, that, ".superclass");
        }
      }
      return sn(this, 'superclass');
    };
    return Super;
  }(Node));
  exports.Parens = Parens = (function(superclass) {
    var prototype = extend$((import$(Parens, superclass).displayName = 'Parens', Parens), superclass).prototype,
        constructor = Parens;
    function Parens(it, keep, string, lb, rb) {
      var this$ = this instanceof ctor$ ? this : new ctor$;
      this$.it = it;
      this$.keep = keep;
      this$.string = string;
      this$.lb = lb;
      this$.rb = rb;
      return this$;
    }
    function ctor$() {}
    ctor$.prototype = prototype;
    Parens.prototype.children = ['it'];
    Parens.prototype.show = function() {
      return this.string && '""';
    };
    prototype.delegate(['isComplex', 'isCallable', 'isArray', 'isRegex'], function(it) {
      return this.it[it]();
    });
    Parens.prototype.isString = function() {
      return this.string || this.it.isString();
    };
    Parens.prototype.unparen = function() {
      if (this.keep) {
        return this;
      } else {
        return this.it.unparen();
      }
    };
    Parens.prototype.compile = function(o, level) {
      var it;
      level == null && (level = o.level);
      it = this.it;
      it.cond || (it.cond = this.cond), it['void'] || (it['void'] = this['void']);
      if (this.calling && (!level || this['void'])) {
        it.head.hushed = true;
      }
      if (!(this.keep || this.newed || level >= LEVEL_OP + PREC[it.op])) {
        return (it.front = this.front, it).compile(o, level || LEVEL_PAREN);
      }
      if (it.isStatement()) {
        return it.compileClosure(o);
      } else {
        return sn(null, sn(this.lb, "("), it.compile(o, LEVEL_PAREN), sn(this.rb, ")"));
      }
    };
    return Parens;
  }(Node));
  exports.Splat = Splat = (function(superclass) {
    var ref$,
        prototype = extend$((import$(Splat, superclass).displayName = 'Splat', Splat), superclass).prototype,
        constructor = Splat;
    function Splat(it, filler) {
      var this$ = this instanceof ctor$ ? this : new ctor$;
      this$.it = it;
      this$.filler = filler;
      return this$;
    }
    function ctor$() {}
    ctor$.prototype = prototype;
    ref$ = Parens.prototype, prototype.children = ref$.children, prototype.isComplex = ref$.isComplex;
    Splat.prototype.isAssignable = YES;
    Splat.prototype.assigns = function(it) {
      return this.it.assigns(it);
    };
    Splat.prototype.compile = function() {
      return this.carp('invalid splat');
    };
    Splat.compileArray = function(o, list, apply) {
      var index,
          i$,
          len$,
          node,
          args,
          atoms,
          ref$;
      expand(list);
      index = 0;
      for (i$ = 0, len$ = list.length; i$ < len$; ++i$) {
        node = list[i$];
        if (node instanceof Splat) {
          break;
        }
        ++index;
      }
      if (index >= list.length) {
        return sn(this, '');
      }
      if (!list[1]) {
        return sn(this, (apply ? Object : ensureArray)(list[0].it).compile(o, LEVEL_LIST));
      }
      args = [];
      atoms = [];
      for (i$ = 0, len$ = (ref$ = list.splice(index, 9e9)).length; i$ < len$; ++i$) {
        node = ref$[i$];
        if (node instanceof Splat) {
          if (atoms.length) {
            args.push(Arr(atoms.splice(0, 9e9)));
          }
          args.push(ensureArray(node.it));
        } else {
          atoms.push(node);
        }
      }
      if (atoms.length) {
        args.push(Arr(atoms));
      }
      return sn(null, (index ? Arr(list) : args.shift()).compile(o, LEVEL_CALL), sn(this, ".concat("), List.compile(o, args), sn(this, ")"));
    };
    function expand(nodes) {
      var index,
          node,
          it;
      index = -1;
      while (node = nodes[++index]) {
        if (node instanceof Splat) {
          it = node.it;
          if (it.isEmpty()) {
            nodes.splice(index--, 1);
          } else if (it instanceof Arr) {
            nodes.splice.apply(nodes, [index, 1].concat(slice$.call(expand(it.items))));
            index += it.items.length - 1;
          }
        }
      }
      return nodes;
    }
    function ensureArray(node) {
      if (node.isArray()) {
        return node;
      }
      return Call.make(JS(util('slice') + '.call'), [node]);
    }
    return Splat;
  }(Node));
  exports.Jump = Jump = (function(superclass) {
    var prototype = extend$((import$(Jump, superclass).displayName = 'Jump', Jump), superclass).prototype,
        constructor = Jump;
    function Jump(verb, label) {
      this.verb = verb;
      this.label = label;
    }
    Jump.prototype.show = function() {
      var that;
      return (this.verb || '') + ((that = this.label) ? ' ' + that : '');
    };
    Jump.prototype.isStatement = YES;
    Jump.prototype.makeReturn = THIS;
    Jump.prototype.getJump = function(ctx) {
      var that,
          ref$;
      ctx || (ctx = {});
      if (!ctx[this.verb]) {
        return this;
      }
      if (that = this.label) {
        return !in$(that, (ref$ = ctx.labels) != null ? ref$ : ctx.labels = []) && this;
      }
    };
    Jump.prototype.compileNode = function(o) {
      var that,
          ref$;
      if (that = this.label) {
        in$(that, (ref$ = o.labels) != null ? ref$ : o.labels = []) || this.carp("unknown label \"" + that + "\"");
      } else {
        o[this.verb] || this.carp("stray " + this.verb);
      }
      return sn(this, this.show() + ';');
    };
    Jump.extended = function(sub) {
      sub.prototype.children = ['it'];
      this[sub.displayName.toLowerCase()] = sub;
    };
    return Jump;
  }(Node));
  exports.Throw = Throw = (function(superclass) {
    var prototype = extend$((import$(Throw, superclass).displayName = 'Throw', Throw), superclass).prototype,
        constructor = Throw;
    function Throw(it) {
      var this$ = this instanceof ctor$ ? this : new ctor$;
      this$.it = it;
      return this$;
    }
    function ctor$() {}
    ctor$.prototype = prototype;
    Throw.prototype.getJump = VOID;
    Throw.prototype.compileNode = function(o) {
      var ref$;
      return sn(this, "throw ", ((ref$ = this.it) != null ? ref$.compile(o, LEVEL_PAREN) : void 8) || 'null', ";");
    };
    return Throw;
  }(Jump));
  exports.Return = Return = (function(superclass) {
    var prototype = extend$((import$(Return, superclass).displayName = 'Return', Return), superclass).prototype,
        constructor = Return;
    function Return(it) {
      var this$ = this instanceof ctor$ ? this : new ctor$;
      if (it && it.value !== 'void') {
        this$.it = it;
      }
      return this$;
    }
    function ctor$() {}
    ctor$.prototype = prototype;
    Return.prototype.getJump = THIS;
    Return.prototype.compileNode = function(o) {
      var that;
      return sn.apply(null, [this, "return"].concat((that = this.it) ? [' ', that.compile(o, LEVEL_PAREN)] : [], [";"]));
    };
    return Return;
  }(Jump));
  exports.While = While = (function(superclass) {
    var prototype = extend$((import$(While, superclass).displayName = 'While', While), superclass).prototype,
        constructor = While;
    function While(test, un, mode) {
      this.un = un;
      mode && (mode instanceof Node ? this.update = mode : this.post = true);
      if (this.post || test.value !== '' + !un) {
        this.test = test;
      }
    }
    While.prototype.children = ['test', 'body', 'update', 'else'];
    While.prototype.aSource = 'test';
    While.prototype.aTargets = ['body', 'update'];
    While.prototype.show = function() {
      return [this.un ? '!' : void 8, this.post ? 'do' : void 8].join('');
    };
    prototype.isStatement = prototype.isArray = YES;
    While.prototype.makeComprehension = function(toAdd, loops) {
      this.isComprehension = true;
      while (loops.length) {
        toAdd = loops.pop().addBody(Block(toAdd));
        if (!toAdd.isComprehension) {
          toAdd.inComprehension = true;
        }
      }
      return this.addBody(Block(toAdd));
    };
    While.prototype.getJump = function(ctx) {
      var i$,
          ref$,
          ref1$,
          len$,
          node;
      ctx || (ctx = {});
      ctx['continue'] = true;
      ctx['break'] = true;
      for (i$ = 0, len$ = (ref$ = ((ref1$ = this.body) != null ? ref1$.lines : void 8) || []).length; i$ < len$; ++i$) {
        node = ref$[i$];
        if (node.getJump(ctx)) {
          return node;
        }
      }
    };
    While.prototype.addBody = function(body) {
      var top;
      this.body = body;
      if (this.guard) {
        this.body = Block(If(this.guard, this.body));
      }
      top = this.body.lines[0];
      if ((top != null ? top.verb : void 8) === 'continue' && !top.label) {
        this.body.lines.length = 0;
      }
      return this;
    };
    While.prototype.addGuard = function(guard) {
      this.guard = guard;
      return this;
    };
    While.prototype.addObjComp = function(objComp) {
      this.objComp = objComp != null ? objComp : true;
      return this;
    };
    While.prototype.makeReturn = function(it) {
      var last,
          ref$,
          ref1$,
          ref2$;
      if (this.hasReturned) {
        return this;
      }
      if (it) {
        if (this.objComp) {
          this.body = Block(this.body.makeReturn(it, true));
        } else {
          if (!(this.body || this.index)) {
            this.addBody(Block(Var(this.index = 'ridx$')));
          }
          last = (ref$ = this.body.lines) != null ? ref$[ref$.length - 1] : void 8;
          if ((this.isComprehension || this.inComprehension) && !(last != null && last.isComprehension)) {
            (ref1$ = this.body).makeReturn.apply(ref1$, arguments);
            if ((ref1$ = this['else']) != null) {
              ref1$.makeReturn.apply(ref1$, arguments);
            }
            this.hasReturned = true;
          } else {
            this.resVar = it;
            if ((ref2$ = this['else']) != null) {
              ref2$.makeReturn.apply(ref2$, arguments);
            }
          }
        }
      } else {
        this.getJump() || (this.returns = true);
      }
      return this;
    };
    While.prototype.compileNode = function(o) {
      var test,
          ref$,
          head,
          that;
      o.loop = true;
      this.test && (this.un ? this.test = this.test.invert() : this.anaphorize());
      if (this.post) {
        return sn(null, sn(this, 'do {'), this.compileBody((o.indent += TAB, o)));
      }
      test = ((ref$ = this.test) != null ? ref$.compile(o, LEVEL_PAREN) : void 8) || '';
      if (!(this.update || this['else'])) {
        head = !snEmpty(test) ? [sn(this, "while ("), test] : [sn(this, 'for (;;')];
      } else {
        head = [sn(this, 'for (')];
        if (this['else']) {
          head.push(this.yet = o.scope.temporary('yet'), " = true");
        }
        head.push(sn(this, ";"), test.toString() && ' ', test, sn(this, ";"));
        if (that = this.update) {
          head.push(' ', that.compile(o, LEVEL_PAREN));
        }
      }
      return sn.apply(null, [null].concat(slice$.call(head), [sn(this, ') {'), this.compileBody((o.indent += TAB, o))]));
    };
    While.prototype.compileBody = function(o) {
      var lines,
          yet,
          tab,
          code,
          ret,
          mid,
          empty,
          _resultName,
          getResultName,
          last,
          hasLoop,
          res,
          temp,
          key$,
          ref$,
          bodyCode,
          this$ = this;
      o['break'] = o['continue'] = true;
      lines = this.body.lines, yet = this.yet, tab = this.tab;
      code = [];
      ret = [];
      mid = [];
      empty = this.objComp ? '{}' : '[]';
      getResultName = function() {
        return _resultName != null ? _resultName : _resultName = o.scope.temporary(this$.objComp ? 'resultObj' : 'results');
      };
      last = lines != null ? lines[lines.length - 1] : void 8;
      if (!(this.isComprehension || this.inComprehension) || (last != null && last.isComprehension)) {
        hasLoop = false;
        if (last != null) {
          last.traverseChildren(function(it) {
            var ref$;
            if (it instanceof Block && (ref$ = it.lines)[ref$.length - 1] instanceof While) {
              hasLoop = true;
            }
          });
        }
        if (this.returns && !this.resVar) {
          this.resVar = res = o.scope.assign(getResultName(), empty);
        }
        if (this.resVar && (last instanceof While || hasLoop)) {
          temp = o.scope.temporary('lresult');
          lines.unshift(Assign(Var(temp), lines[lines.length - 1].objComp ? Obj() : Arr(), '='));
          if (lines[key$ = lines.length - 1] != null) {
            lines[key$] = lines[key$].makeReturn(temp);
          }
          mid.push(TAB, Chain(Var(this.resVar)).add(Index(Key('push'), '.', true)).add(Call([Chain(Var(temp))])).compile(o), ";\n" + this.tab);
        } else {
          this.hasReturned = true;
          if (this.resVar) {
            this.body.makeReturn(this.resVar);
          }
        }
      }
      if (this.returns) {
        if ((!last instanceof While && !this.hasReturned) || this.isComprehension || this.inComprehension) {
          if (lines[key$ = lines.length - 1] != null) {
            lines[key$] = lines[key$].makeReturn(res = o.scope.assign(getResultName(), empty), this.objComp);
          }
        }
        ret.push("\n" + this.tab + "return ", res || empty, ";");
        if ((ref$ = this['else']) != null) {
          ref$.makeReturn();
        }
      }
      yet && lines.unshift(JS(yet + " = false;"));
      if (!snEmpty(bodyCode = this.body.compile(o, LEVEL_TOP))) {
        code.push("\n", bodyCode, "\n" + tab);
      }
      code.push.apply(code, mid);
      code.push('}');
      if (this.post) {
        code.push(sn(this, " while ("), this.test.compile((o.tab = tab, o), LEVEL_PAREN), sn(this, ");"));
      }
      if (yet) {
        code.push(sn(this, " if ("), yet, sn(this, ") "), this.compileBlock(o, Block(this['else'])));
        o.scope.free(yet);
      }
      return sn.apply(null, [null].concat(slice$.call(code), slice$.call(ret)));
    };
    return While;
  }(Node));
  exports.For = For = (function(superclass) {
    var prototype = extend$((import$(For, superclass).displayName = 'For', For), superclass).prototype,
        constructor = For;
    function For(it) {
      var i$,
          x$,
          ref$,
          len$;
      importAll$(this, it);
      if (this.item instanceof Var && !this.item.value) {
        this.item = null;
      }
      for (i$ = 0, len$ = (ref$ = this.kind || []).length; i$ < len$; ++i$) {
        x$ = ref$[i$];
        this[x$] = true;
      }
      if (this.own && !this.object) {
        this.carp('`for own` requires `of`');
      }
    }
    For.prototype.children = ['item', 'source', 'from', 'to', 'step', 'body'];
    For.prototype.aSource = null;
    For.prototype.show = function() {
      return ((this.kind || []).concat(this.index)).join(' ');
    };
    For.prototype.addBody = function(body) {
      var hasYield,
          ref$,
          x$,
          that,
          this$ = this;
      hasYield = !!body.traverseChildren(function(child) {
        if (child instanceof Yield) {
          return true;
        }
      });
      if (this['let']) {
        if (ref$ = this.ref, delete this.ref, ref$) {
          this.item = Literal('..');
        }
        body = Block(Call['let']((x$ = [], (that = this.index) && x$.push(Assign(Var(that), Literal('index$$'))), (that = this.item) && x$.push(Assign(that, Literal('item$$'))), x$), body, hasYield));
      }
      superclass.prototype.addBody.call(this, body);
      if (this.guard && this['let'] && (this.index || this.item)) {
        this.body.lines[0]['if'].traverseChildren(function(it) {
          if (it instanceof Var) {
            if (this$.index && it.value === this$.index) {
              it.value = 'index$$';
            }
            if (this$.item && it.value === this$.item.value) {
              it.value = 'item$$';
            }
          }
        });
      }
      if (this['let']) {
        if (hasYield) {
          this.body = Block(Yield('yieldfrom', body));
        }
        delete this.index;
        delete this.item;
      }
      return this;
    };
    For.prototype.compileNode = function(o) {
      var temps,
          idx,
          ref$,
          pvar,
          step,
          tvar,
          tail,
          fvar,
          vars,
          eq,
          cond,
          svar,
          srcPart,
          lvar,
          head,
          that,
          body;
      o.loop = true;
      temps = this.temps = [];
      if (this.object && this.index) {
        o.scope.declare(idx = this.index);
      } else {
        temps.push(idx = o.scope.temporary('i'));
      }
      if (!this.body) {
        this.addBody(Block(Var(idx)));
      }
      if (!this.object) {
        ref$ = (this.step || Literal(1)).compileLoopReference(o, 'step'), pvar = ref$[0], step = ref$[1];
        pvar === step || temps.push(pvar);
      }
      if (this.from) {
        if (this.ref) {
          this.item = Var(idx);
        }
        ref$ = this.to.compileLoopReference(o, 'to'), tvar = ref$[0], tail = ref$[1];
        fvar = this.from.compile(o, LEVEL_LIST);
        vars = idx + " = " + fvar;
        if (tail !== tvar) {
          vars += ", " + tail;
          temps.push(tvar);
        }
        if (!this.step && +fvar > +tvar) {
          pvar = step = -1;
        }
        eq = this.op === 'til' ? '' : '=';
        cond = +pvar ? idx + " " + '<>'.charAt(pvar < 0) + eq + " " + tvar : pvar + " < 0 ? " + idx + " >" + eq + " " + tvar + " : " + idx + " <" + eq + " " + tvar;
      } else {
        if (this.ref) {
          this.item = Var(o.scope.temporary('x'));
        }
        if (this.item || this.object && this.own || this['let']) {
          ref$ = this.source.compileLoopReference(o, 'ref', !this.object, true), svar = ref$[0], srcPart = ref$[1];
          svar === srcPart || temps.push(svar);
        } else {
          svar = srcPart = this.source.compile(o, LEVEL_PAREN);
        }
        if (!this.object) {
          if (0 > pvar && ~~pvar === +pvar) {
            vars = idx + " = " + srcPart + ".length - 1";
            cond = idx + " >= 0";
          } else {
            temps.push(lvar = o.scope.temporary('len'));
            vars = idx + " = 0, " + lvar + " = " + srcPart + ".length";
            cond = idx + " < " + lvar;
          }
        }
      }
      this['else'] && (this.yet = o.scope.temporary('yet'));
      head = [sn(this, 'for (')];
      if (this.object) {
        head.push(idx, " in ");
      }
      if (that = this.yet) {
        head.push(that, " = true, ");
      }
      if (this.object) {
        head.push(srcPart);
      } else {
        step === pvar || (vars += ', ' + step);
        head.push(vars, "; ", cond, "; " + (1 == Math.abs(pvar) ? (pvar < 0 ? '--' : '++') + idx : idx + (pvar < 0 ? ' -= ' + pvar.toString().slice(1) : ' += ' + pvar)));
      }
      this.own && head.push(sn(this, ") if ("), o.scope.assign('own$', '{}.hasOwnProperty'), ".call(", svar, ", ", idx, ")");
      head.push(sn(this, ') {'));
      if (this['let']) {
        this.body.traverseChildren(function(it) {
          switch (it.value) {
            case 'index$$':
              it.value = idx;
              break;
            case 'item$$':
              it.value = svar + "[" + idx + "]";
          }
        });
      }
      o.indent += TAB;
      if (this.index && !this.object) {
        head.push('\n' + o.indent, Assign(Var(this.index), JS(idx)).compile(o, LEVEL_TOP), ';');
      }
      if (this.item && !this.item.isEmpty() && !this.from) {
        head.push('\n' + o.indent, Assign(this.item, JS(svar + "[" + idx + "]")).compile(o, LEVEL_TOP), ';');
      }
      if (this.ref) {
        o.ref = this.item.value;
      }
      body = this.compileBody(o);
      if ((this.item || (this.index && !this.object)) && '}' === body.toString().charAt(0)) {
        head.push('\n' + this.tab);
      }
      return sn.apply(null, [null].concat(slice$.call(head), [body]));
    };
    return For;
  }(While));
  exports.StepSlice = StepSlice = (function(superclass) {
    var prototype = extend$((import$(StepSlice, superclass).displayName = 'StepSlice', StepSlice), superclass).prototype,
        constructor = StepSlice;
    StepSlice.prototype.makeReturn = function(makeReturnArg) {
      this.makeReturnArg = makeReturnArg;
      return superclass.prototype.makeReturn.apply(this, arguments);
    };
    StepSlice.prototype.compileNode = function(o) {
      var ref$,
          sub,
          ref,
          temps,
          code;
      this.index = o.scope.temporary('x');
      ref$ = this.target.unwrap().cache(o), sub = ref$[0], ref = ref$[1], temps = ref$[2];
      this.guard = Binary('<', Literal(this.index), Chain(ref).add(Index(Key('length'))));
      this.makeComprehension(Chain(ref).add(Index(Literal(this.index))), this);
      if (this.makeReturnArg != null) {
        this.makeReturn(this.makeReturnArg);
      }
      code = [];
      if (temps) {
        code.push(sub.compile(o), ';' + '\n' + o.indent);
      }
      code.push(superclass.prototype.compileNode.apply(this, arguments));
      return sn.apply(null, [this].concat(slice$.call(code)));
    };
    function StepSlice() {
      StepSlice.superclass.apply(this, arguments);
    }
    return StepSlice;
  }(For));
  exports.Try = Try = (function(superclass) {
    var prototype = extend$((import$(Try, superclass).displayName = 'Try', Try), superclass).prototype,
        constructor = Try;
    function Try(attempt, thrown, recovery, ensure) {
      var ref$;
      this.attempt = attempt;
      this.thrown = thrown;
      this.recovery = recovery;
      this.ensure = ensure;
      if ((ref$ = this.recovery) != null) {
        ref$.lines.unshift(Assign(this.thrown || Var('e'), Var('e$')));
      }
    }
    Try.prototype.children = ['attempt', 'recovery', 'ensure'];
    Try.prototype.show = function() {
      return this.thrown;
    };
    Try.prototype.isStatement = YES;
    Try.prototype.isCallable = function() {
      var ref$;
      return ((ref$ = this.recovery) != null ? ref$.isCallable() : void 8) && this.attempt.isCallable();
    };
    Try.prototype.getJump = function(it) {
      var ref$;
      return this.attempt.getJump(it) || ((ref$ = this.recovery) != null ? ref$.getJump(it) : void 8);
    };
    Try.prototype.makeReturn = function() {
      var ref$;
      this.attempt = (ref$ = this.attempt).makeReturn.apply(ref$, arguments);
      if (this.recovery != null) {
        this.recovery = (ref$ = this.recovery).makeReturn.apply(ref$, arguments);
      }
      return this;
    };
    Try.prototype.compileNode = function(o) {
      var code,
          that;
      o.indent += TAB;
      code = [sn(this, 'try '), this.compileBlock(o, this.attempt)];
      if (that = this.recovery || !this.ensure && JS('')) {
        code.push(sn(that, ' catch (e$) '), this.compileBlock(o, that));
      }
      if (that = this.ensure) {
        code.push(sn(that, ' finally '), this.compileBlock(o, that));
      }
      return sn.apply(null, [null].concat(slice$.call(code)));
    };
    return Try;
  }(Node));
  exports.Switch = Switch = (function(superclass) {
    var prototype = extend$((import$(Switch, superclass).displayName = 'Switch', Switch), superclass).prototype,
        constructor = Switch;
    function Switch(type, topic, cases, $default) {
      var last,
          ref$;
      this.type = type;
      this.topic = topic;
      this.cases = cases;
      this['default'] = $default;
      if (type === 'match') {
        if (topic) {
          this.target = Arr(topic);
        }
        this.topic = null;
      } else {
        if (topic) {
          if (topic.length > 1) {
            throw "can't have more than one topic in switch statement";
          }
          this.topic = this.topic[0];
        }
      }
      if (this.cases.length && (last = (ref$ = this.cases)[ref$.length - 1]).tests.length === 1 && last.tests[0] instanceof Var && last.tests[0].value === '_') {
        this.cases.pop();
        this['default'] = last.body;
      }
    }
    Switch.prototype.children = ['topic', 'cases', 'default'];
    Switch.prototype.aSource = 'topic';
    Switch.prototype.aTargets = ['cases', 'default'];
    Switch.prototype.show = function() {
      return this.type;
    };
    Switch.prototype.isStatement = YES;
    Switch.prototype.isCallable = function() {
      var i$,
          ref$,
          len$,
          c;
      for (i$ = 0, len$ = (ref$ = this.cases).length; i$ < len$; ++i$) {
        c = ref$[i$];
        if (!c.isCallable()) {
          return false;
        }
      }
      if (this['default']) {
        return this['default'].isCallable();
      } else {
        return true;
      }
    };
    Switch.prototype.getJump = function(ctx) {
      var i$,
          ref$,
          len$,
          c,
          that;
      ctx || (ctx = {});
      ctx['break'] = true;
      for (i$ = 0, len$ = (ref$ = this.cases).length; i$ < len$; ++i$) {
        c = ref$[i$];
        if (that = c.body.getJump(ctx)) {
          return that;
        }
      }
      return (ref$ = this['default']) != null ? ref$.getJump(ctx) : void 8;
    };
    Switch.prototype.makeReturn = function() {
      var i$,
          ref$,
          len$,
          c;
      for (i$ = 0, len$ = (ref$ = this.cases).length; i$ < len$; ++i$) {
        c = ref$[i$];
        c.makeReturn.apply(c, arguments);
      }
      if ((ref$ = this['default']) != null) {
        ref$.makeReturn.apply(ref$, arguments);
      }
      return this;
    };
    Switch.prototype.compileNode = function(o) {
      var tab,
          ref$,
          targetNode,
          target,
          topic,
          t,
          code,
          stop,
          i$,
          len$,
          i,
          c,
          that;
      tab = this.tab;
      if (this.target) {
        ref$ = Chain(this.target).cacheReference(o), targetNode = ref$[0], target = ref$[1];
      }
      topic = this.type === 'match' ? (t = target ? [targetNode] : [], Block(t.concat([Literal('false')])).compile(o, LEVEL_PAREN)) : !!this.topic && this.anaphorize().compile(o, LEVEL_PAREN);
      code = [sn(this, "switch (", snSafe(topic), ") {\n")];
      stop = this['default'] || this.cases.length - 1;
      o['break'] = true;
      for (i$ = 0, len$ = (ref$ = this.cases).length; i$ < len$; ++i$) {
        i = i$;
        c = ref$[i$];
        code.push(c.compileCase(o, tab, i === stop, this.type === 'match' || !topic, this.type, target));
      }
      if (this['default']) {
        o.indent = tab + TAB;
        if (that = this['default'].compile(o, LEVEL_TOP)) {
          code.push(tab + "default:\n", that, "\n");
        }
      }
      return sn.apply(null, [null].concat(slice$.call(code), [tab + '}']));
    };
    return Switch;
  }(Node));
  exports.Case = Case = (function(superclass) {
    var prototype = extend$((import$(Case, superclass).displayName = 'Case', Case), superclass).prototype,
        constructor = Case;
    function Case(tests, body) {
      this.tests = tests;
      this.body = body;
    }
    Case.prototype.children = ['tests', 'body'];
    Case.prototype.isCallable = function() {
      return this.body.isCallable();
    };
    Case.prototype.makeReturn = function() {
      var ref$,
          ref1$;
      if (((ref$ = (ref1$ = this.body.lines)[ref1$.length - 1]) != null ? ref$.value : void 8) !== 'fallthrough') {
        (ref1$ = this.body).makeReturn.apply(ref1$, arguments);
      }
      return this;
    };
    Case.prototype.compileCase = function(o, tab, nobr, bool, type, target) {
      var tests,
          i$,
          ref$,
          len$,
          test,
          j$,
          ref1$,
          len1$,
          t,
          i,
          tar,
          binary,
          that,
          code,
          lines,
          last,
          ft,
          bodyCode;
      tests = [];
      for (i$ = 0, len$ = (ref$ = this.tests).length; i$ < len$; ++i$) {
        test = ref$[i$];
        test = test.expandSlice(o).unwrap();
        if (test instanceof Arr && type !== 'match') {
          for (j$ = 0, len1$ = (ref1$ = test.items).length; j$ < len1$; ++j$) {
            t = ref1$[j$];
            tests.push(t);
          }
        } else {
          tests.push(test);
        }
      }
      tests.length || tests.push(Literal('void'));
      if (type === 'match') {
        for (i$ = 0, len$ = tests.length; i$ < len$; ++i$) {
          i = i$;
          test = tests[i$];
          tar = Chain(target).add(Index(Literal(i), '.', true));
          tests[i] = Parens(Chain(test).autoCompare(target ? [tar] : null));
        }
      }
      if (bool) {
        binary = type === 'match' ? '&&' : '||';
        t = tests[0];
        i = 0;
        while (that = tests[++i]) {
          t = Binary(binary, t, that);
        }
        tests = [(this.t = t, this.aSource = 't', this.aTargets = ['body'], this).anaphorize().invert()];
      }
      code = [];
      for (i$ = 0, len$ = tests.length; i$ < len$; ++i$) {
        t = tests[i$];
        code.push(tab, sn(t, "case ", t.compile(o, LEVEL_PAREN), ":\n"));
      }
      lines = this.body.lines;
      last = lines[lines.length - 1];
      if (ft = (last != null ? last.value : void 8) === 'fallthrough') {
        lines[lines.length - 1] = JS('// fallthrough');
      }
      o.indent = tab += TAB;
      if (!snEmpty(bodyCode = this.body.compile(o, LEVEL_TOP))) {
        code.push(bodyCode, '\n');
      }
      if (!(nobr || ft || last instanceof Jump)) {
        code.push(tab + 'break;\n');
      }
      return sn.apply(null, [null].concat(slice$.call(code)));
    };
    return Case;
  }(Node));
  exports.If = If = (function(superclass) {
    var prototype = extend$((import$(If, superclass).displayName = 'If', If), superclass).prototype,
        constructor = If;
    function If($if, then, un) {
      var this$ = this instanceof ctor$ ? this : new ctor$;
      this$['if'] = $if;
      this$.then = then;
      this$.un = un;
      return this$;
    }
    function ctor$() {}
    ctor$.prototype = prototype;
    If.prototype.children = ['if', 'then', 'else'];
    If.prototype.aSource = 'if';
    If.prototype.aTargets = ['then'];
    If.prototype.show = function() {
      return this.un && '!';
    };
    If.prototype.terminator = '';
    prototype.delegate(['isCallable', 'isArray', 'isString', 'isRegex'], function(it) {
      var ref$;
      return ((ref$ = this['else']) != null ? ref$[it]() : void 8) && this.then[it]();
    });
    If.prototype.getJump = function(it) {
      var ref$;
      return this.then.getJump(it) || ((ref$ = this['else']) != null ? ref$.getJump(it) : void 8);
    };
    If.prototype.makeReturn = function() {
      var ref$;
      this.then = (ref$ = this.then).makeReturn.apply(ref$, arguments);
      if (this['else'] != null) {
        this['else'] = (ref$ = this['else']).makeReturn.apply(ref$, arguments);
      }
      return this;
    };
    If.prototype.compileNode = function(o) {
      if (this.un) {
        this['if'] = this['if'].invert();
      } else {
        this.soak || this.anaphorize();
      }
      if (o.level) {
        return this.compileExpression(o);
      } else {
        return this.compileStatement(o);
      }
    };
    If.prototype.compileStatement = function(o) {
      var code,
          els;
      code = [sn(this, "if (", this['if'].compile(o, LEVEL_PAREN), ") ")];
      o.indent += TAB;
      code.push(this.compileBlock(o, Block(this.then)));
      if (!(els = this['else'])) {
        return sn.apply(null, [null].concat(slice$.call(code)));
      }
      return sn.apply(null, [null].concat(slice$.call(code), [sn(els, ' else '), els instanceof constructor ? els.compile((o.indent = this.tab, o), LEVEL_TOP) : this.compileBlock(o, els)]));
    };
    If.prototype.compileExpression = function(o) {
      var thn,
          els,
          code,
          pad;
      thn = this.then, els = this['else'] || Literal('void');
      this['void'] && (thn['void'] = els['void'] = true);
      if (!this['else'] && (this.cond || this['void'])) {
        return Parens(Binary('&&', this['if'], thn)).compile(o);
      }
      code = [sn(this, this['if'].compile(o, LEVEL_COND))];
      pad = els.isComplex() ? '\n' + (o.indent += TAB) : ' ';
      code.push(pad + "", sn(thn, "? "), thn.compile(o, LEVEL_LIST), pad + "", sn(els, ": "), els.compile(o, LEVEL_LIST));
      if (o.level < LEVEL_COND) {
        return sn.apply(null, [null].concat(slice$.call(code)));
      } else {
        return sn(null, "(", code, ")");
      }
    };
    If.unfoldSoak = function(o, parent, name) {
      var that;
      if (that = parent[name].unfoldSoak(o)) {
        parent[name] = that.then;
        return that.cond = parent.cond, that['void'] = parent['void'], that.then = Chain(parent), that;
      }
    };
    return If;
  }(Node));
  exports.Label = Label = (function(superclass) {
    var ref$,
        prototype = extend$((import$(Label, superclass).displayName = 'Label', Label), superclass).prototype,
        constructor = Label;
    function Label(label, it) {
      var fun;
      this.label = label || '_';
      this.it = it;
      if (fun = (it instanceof Fun || it instanceof Class) && it || it.calling && it.it.head) {
        fun.name || (fun.name = this.label, fun.labeled = true);
        return it;
      }
    }
    ref$ = Parens.prototype, prototype.children = ref$.children, prototype.isCallable = ref$.isCallable, prototype.isArray = ref$.isArray;
    Label.prototype.show = function() {
      return this.label;
    };
    Label.prototype.isStatement = YES;
    Label.prototype.getJump = function(ctx) {
      var ref$;
      ctx || (ctx = {});
      ((ref$ = ctx.labels) != null ? ref$ : ctx.labels = []).push(this.label);
      return this.it.getJump((ctx['break'] = true, ctx));
    };
    Label.prototype.makeReturn = function() {
      var ref$;
      this.it = (ref$ = this.it).makeReturn.apply(ref$, arguments);
      return this;
    };
    Label.prototype.compileNode = function(o) {
      var label,
          it,
          labels;
      label = this.label, it = this.it;
      labels = o.labels = slice$.call(o.labels || []);
      if (in$(label, labels)) {
        this.carp("duplicate label \"" + label + "\"");
      }
      labels.push(label);
      it.isStatement() || (it = Block(it));
      return sn(null, sn(this, label, ": "), it instanceof Block ? (o.indent += TAB, this.compileBlock(o, it)) : it.compile(o));
    };
    return Label;
  }(Node));
  exports.Cascade = Cascade = (function(superclass) {
    var prototype = extend$((import$(Cascade, superclass).displayName = 'Cascade', Cascade), superclass).prototype,
        constructor = Cascade;
    function Cascade(input, output, prog1) {
      var this$ = this instanceof ctor$ ? this : new ctor$;
      this$.input = input;
      this$.output = output;
      this$.prog1 = prog1;
      return this$;
    }
    function ctor$() {}
    ctor$.prototype = prototype;
    Cascade.prototype.show = function() {
      return this.prog1;
    };
    Cascade.prototype.children = ['input', 'output'];
    Cascade.prototype.terminator = '';
    prototype.delegate(['isCallable', 'isArray', 'isString', 'isRegex'], function(it) {
      return this[this.prog1 ? 'input' : 'output'][it]();
    });
    Cascade.prototype.getJump = function(it) {
      return this.output.getJump(it);
    };
    Cascade.prototype.makeReturn = function(ret) {
      this.ret = ret;
      return this;
    };
    Cascade.prototype.compileNode = function(o) {
      var level,
          input,
          output,
          prog1,
          ref,
          ref$,
          code,
          out;
      level = o.level;
      input = this.input, output = this.output, prog1 = this.prog1, ref = this.ref;
      if (prog1 && ('ret' in this || level && !this['void'])) {
        output.add((ref$ = Literal('..'), ref$.cascadee = true, ref$));
      }
      if ('ret' in this) {
        output = output.makeReturn(this.ret);
      }
      if (ref) {
        prog1 || (output = Assign(Var(ref), output));
      } else {
        ref = o.scope.temporary('x');
      }
      if (input instanceof Cascade) {
        input.ref = ref;
      } else {
        input && (input = Assign(Var(ref), input));
      }
      o.level && (o.level = LEVEL_PAREN);
      code = [input.compile(o)];
      out = Block(output).compile((o.ref = new String(ref), o));
      if (prog1 === 'cascade' && !o.ref.erred) {
        this.carp("unreferred cascadee");
      }
      if (!level) {
        return sn.apply(null, [null].concat(slice$.call(code), [input.terminator, "\n", out]));
      }
      code.push(", ", out);
      if (level > LEVEL_PAREN) {
        return sn.apply(null, [null, "("].concat(slice$.call(code), [")"]));
      } else {
        return sn.apply(null, [null].concat(slice$.call(code)));
      }
    };
    return Cascade;
  }(Node));
  exports.JS = JS = (function(superclass) {
    var prototype = extend$((import$(JS, superclass).displayName = 'JS', JS), superclass).prototype,
        constructor = JS;
    function JS(code, literal, comment) {
      var this$ = this instanceof ctor$ ? this : new ctor$;
      this$.code = code;
      this$.literal = literal;
      this$.comment = comment;
      return this$;
    }
    function ctor$() {}
    ctor$.prototype = prototype;
    JS.prototype.show = function() {
      if (this.comment) {
        return this.code;
      } else {
        return "`" + this.code + "`";
      }
    };
    JS.prototype.terminator = '';
    prototype.isAssignable = prototype.isCallable = function() {
      return !this.comment;
    };
    JS.prototype.compile = function(it) {
      return sn(this, snSafe(this.literal ? entab(this.code, it.indent) : this.code));
    };
    return JS;
  }(Node));
  exports.Require = Require = (function(superclass) {
    var prototype = extend$((import$(Require, superclass).displayName = 'Require', Require), superclass).prototype,
        constructor = Require;
    function Require(body) {
      var this$ = this instanceof ctor$ ? this : new ctor$;
      this$.body = body;
      return this$;
    }
    function ctor$() {}
    ctor$.prototype = prototype;
    Require.prototype.children = ['body'];
    Require.prototype.compile = function(o) {
      var getValue,
          processItem,
          code,
          i$,
          ref$,
          len$,
          item,
          this$ = this;
      getValue = function(item, throwError) {
        switch (false) {
          case !(item instanceof Key):
            return item.name;
          case !(item instanceof Var):
            return item.value;
          case !(item instanceof Literal):
            return item.value;
          default:
            if (throwError) {
              return this$.carp('invalid require! argument');
            } else {
              return item;
            }
        }
      };
      processItem = function(item) {
        var ref$,
            asg,
            value,
            asgValue,
            toAsg,
            main;
        ref$ = (function() {
          switch (false) {
            case !(item instanceof Prop):
              return [item.val, item.key];
            default:
              return [item, item];
          }
        }()), asg = ref$[0], value = ref$[1];
        asgValue = getValue(asg);
        toAsg = toString$.call(asgValue).slice(8, -1) === 'String' ? CopyL(asg, Var(nameFromPath(asgValue))) : asg;
        value = stripString(getValue(value, true));
        main = Chain(CopyL(this, Var('require'))).add(Call([Literal("'" + value + "'")]));
        return sn(item, Assign(toAsg, main).compile(o));
      };
      if (this.body.items != null) {
        code = [];
        for (i$ = 0, len$ = (ref$ = this.body.items).length; i$ < len$; ++i$) {
          item = ref$[i$];
          code.push(processItem(item), ";\n" + o.indent);
        }
        code.pop();
        return sn.apply(null, [null].concat(slice$.call(code)));
      } else {
        return sn(null, processItem(this.body));
      }
    };
    return Require;
  }(Node));
  exports.Util = Util = (function(superclass) {
    var prototype = extend$((import$(Util, superclass).displayName = 'Util', Util), superclass).prototype,
        constructor = Util;
    function Util(verb) {
      var this$ = this instanceof ctor$ ? this : new ctor$;
      this$.verb = verb;
      return this$;
    }
    function ctor$() {}
    ctor$.prototype = prototype;
    Util.prototype.show = Jump.prototype.show;
    Util.prototype.isCallable = YES;
    Util.prototype.compile = function() {
      return sn(this, util(this.verb));
    };
    Util.Extends = function() {
      return Call.make(Util('extend'), [arguments[0], arguments[1]]);
    };
    return Util;
  }(Node));
  exports.Vars = Vars = (function(superclass) {
    var prototype = extend$((import$(Vars, superclass).displayName = 'Vars', Vars), superclass).prototype,
        constructor = Vars;
    function Vars(vars) {
      var this$ = this instanceof ctor$ ? this : new ctor$;
      this$.vars = vars;
      return this$;
    }
    function ctor$() {}
    ctor$.prototype = prototype;
    Vars.prototype.children = ['vars'];
    Vars.prototype.makeReturn = THIS;
    Vars.prototype.compile = function(o, level) {
      var i$,
          ref$,
          len$,
          v,
          value;
      for (i$ = 0, len$ = (ref$ = this.vars).length; i$ < len$; ++i$) {
        v = ref$[i$], value = v.value;
        if (!(v instanceof Var)) {
          v.carp('invalid variable declaration');
        }
        if (o.scope.check(value)) {
          v.carp("redeclaration of \"" + value + "\"");
        }
        o.scope.declare(value, v);
      }
      return sn(this, Literal('void').compile(o, level));
    };
    return Vars;
  }(Node));
  exports.L = function(a, b, node) {
    if (node && typeof node === "object") {
      node.first_line = a.first_line + 1;
      node.first_column = a.first_column;
      node.last_line = b.last_line + 1;
      node.last_column = b.last_column;
      node.line = a.first_line + 1;
      node.column = a.first_column;
    }
    return node;
  };
  exports.CopyL = CopyL = function(a, node) {
    if (node && typeof node === "object") {
      node.first_line = a.first_line;
      node.first_column = a.first_column;
      node.last_line = a.last_line;
      node.last_column = a.last_column;
      node.line = a.line;
      node.column = a.column;
    }
    return node;
  };
  exports.Box = function(v) {
    if (typeof v === "object") {
      return v;
    } else {
      return new v.constructor(v);
    }
  };
  exports.Decl = function(type, nodes, lno) {
    if (!nodes[0]) {
      throw SyntaxError("empty " + type + " on line " + lno);
    }
    return DECLS[type](nodes);
  };
  DECLS = {
    'export': function(lines) {
      var i,
          out,
          node,
          that,
          ref$;
      i = -1;
      out = Util('out');
      while (node = lines[++i]) {
        if (node instanceof Block) {
          lines.splice.apply(lines, [i--, 1].concat(slice$.call(node.lines)));
          continue;
        }
        if (that = node instanceof Fun && node.name) {
          lines.splice(i++, 0, Assign(Chain(out, [Index(Key(that))]), Var(that)));
          continue;
        }
        lines[i] = (that = node.varName() || node instanceof Assign && node.left.varName() || node instanceof Class && ((ref$ = node.title) != null ? ref$.varName() : void 8)) ? Assign(Chain(out, [Index(Key(that))]), node) : Import(out, node);
      }
      return Block(lines);
    },
    'import': function(lines, all) {
      var i$,
          len$,
          i,
          line;
      for (i$ = 0, len$ = lines.length; i$ < len$; ++i$) {
        i = i$;
        line = lines[i$];
        lines[i] = Import(Literal('this'), line, all);
      }
      return Block(lines);
    },
    importAll: function(it) {
      return this['import'](it, true);
    },
    'const': function(lines) {
      var i$,
          len$,
          node;
      for (i$ = 0, len$ = lines.length; i$ < len$; ++i$) {
        node = lines[i$];
        node.op === '=' || node.carp('invalid constant variable declaration');
        node['const'] = true;
      }
      return Block(lines);
    },
    'var': Vars
  };
  function Scope(parent, shared) {
    this.parent = parent;
    this.shared = shared;
    this.variables = {};
  }
  ref$ = Scope.prototype;
  ref$.READ_ONLY = {
    'const': 'constant',
    'function': 'function',
    undefined: 'undeclared'
  };
  ref$.add = function(name, type, node) {
    var t,
        that;
    if (node && (t = this.variables[name + "."])) {
      if (that = this.READ_ONLY[t] || this.READ_ONLY[type]) {
        node.carp("redeclaration of " + that + " \"" + name + "\"");
      } else if (t === type && type === 'arg') {
        node.carp("duplicate parameter \"" + name + "\"");
      } else if (t === 'upvar') {
        node.carp("accidental shadow of \"" + name + "\"");
      }
      if (t === 'arg' || t === 'function') {
        return name;
      }
    }
    this.variables[name + "."] = type;
    return name;
  };
  ref$.get = function(name) {
    return this.variables[name + "."];
  };
  ref$.declare = function(name, node, constant) {
    var that,
        scope;
    if (that = this.shared) {
      if (this.check(name)) {
        return;
      }
      scope = that;
    } else {
      scope = this;
    }
    return scope.add(name, constant ? 'const' : 'var', node);
  };
  ref$.assign = function(name, value) {
    return this.add(name, {value: value});
  };
  ref$.temporary = function(name) {
    var ref$;
    name || (name = 'ref');
    while ((ref$ = this.variables[name + "$."]) !== 'reuse' && ref$ !== void 8) {
      name = name.length < 2 && name < 'z' ? String.fromCharCode(name.charCodeAt() + 1) : name.replace(/\d*$/, fn$);
    }
    return this.add(name + '$', 'var');
    function fn$(it) {
      return ++it;
    }
  };
  ref$.free = function(name) {
    return this.add(name, 'reuse');
  };
  ref$.check = function(name, above) {
    var type,
        ref$;
    if ((type = this.variables[name + "."]) || !above) {
      return type;
    }
    return (ref$ = this.parent) != null ? ref$.check(name, above) : void 8;
  };
  ref$.checkReadOnly = function(name) {
    var that,
        ref$,
        key$;
    if (that = this.READ_ONLY[this.check(name, true)]) {
      return that;
    }
    (ref$ = this.variables)[key$ = name + "."] || (ref$[key$] = 'upvar');
    return '';
  };
  ref$.emit = function(code, tab) {
    var vrs,
        asn,
        fun,
        name,
        ref$,
        type,
        that,
        val,
        declCode;
    vrs = [];
    asn = [];
    fun = [];
    for (name in ref$ = this.variables) {
      type = ref$[name];
      name = name.slice(0, -1);
      if (type === 'var' || type === 'const' || type === 'reuse') {
        vrs.push(name, ", ");
      } else if (that = type.value) {
        if (~(val = entab(that, tab)).toString().lastIndexOf('function(', 0)) {
          if (val instanceof SourceNode) {
            snRemoveLeft(val, 8);
          } else {
            val = val.slice(8);
          }
          fun.push("function ", name, val, "\n" + tab);
        } else {
          asn.push(name, " = ", val, ", ");
        }
      }
    }
    declCode = vrs.concat(asn);
    declCode.pop();
    fun.pop();
    if (declCode.length > 0) {
      code = sn.apply(null, [this, tab + "var "].concat(slice$.call(declCode), [";\n", code]));
    }
    if (fun.length > 0) {
      return sn.apply(null, [this, code, "\n" + tab].concat(slice$.call(fun)));
    } else {
      return sn(this, code);
    }
  };
  function YES() {
    return true;
  }
  function NO() {
    return false;
  }
  function THIS() {
    return this;
  }
  function VOID() {}
  UTILS = {
    clone: 'function(it){\n  function fun(){} fun.prototype = it;\n  return new fun;\n}',
    extend: 'function(sub, sup){\n  function fun(){} fun.prototype = (sub.superclass = sup).prototype;\n  (sub.prototype = new fun).constructor = sub;\n  if (typeof sup.extended == \'function\') sup.extended(sub);\n  return sub;\n}',
    bind: 'function(obj, key, target){\n  return function(){ return (target || obj)[key].apply(obj, arguments) };\n}',
    'import': 'function(obj, src){\n  var own = {}.hasOwnProperty;\n  for (var key in src) if (own.call(src, key)) obj[key] = src[key];\n  return obj;\n}',
    importAll: 'function(obj, src){\n  for (var key in src) obj[key] = src[key];\n  return obj;\n}',
    repeatString: 'function(str, n){\n  for (var r = \'\'; n > 0; (n >>= 1) && (str += str)) if (n & 1) r += str;\n  return r;\n}',
    repeatArray: 'function(arr, n){\n  for (var r = []; n > 0; (n >>= 1) && (arr = arr.concat(arr)))\n    if (n & 1) r.push.apply(r, arr);\n  return r;\n}',
    'in': 'function(x, xs){\n  var i = -1, l = xs.length >>> 0;\n  while (++i < l) if (x === xs[i]) return true;\n  return false;\n}',
    out: 'typeof exports != \'undefined\' && exports || this',
    curry: 'function(f, bound){\n  var context,\n  _curry = function(args) {\n    return f.length > 1 ? function(){\n      var params = args ? args.concat() : [];\n      context = bound ? context || this : this;\n      return params.push.apply(params, arguments) <\n          f.length && arguments.length ?\n        _curry.call(context, params) : f.apply(context, params);\n    } : f;\n  };\n  return _curry();\n}',
    flip: 'function(f){\n  return curry$(function (x, y) { return f(y, x); });\n}',
    partialize: 'function(f, args, where){\n  var context = this;\n  return function(){\n    var params = slice$.call(arguments), i,\n        len = params.length, wlen = where.length,\n        ta = args ? args.concat() : [], tw = where ? where.concat() : [];\n    for(i = 0; i < len; ++i) { ta[tw[0]] = params[i]; tw.shift(); }\n    return len < wlen && len ?\n      partialize$.apply(context, [f, ta, tw]) : f.apply(context, ta);\n  };\n}',
    not: 'function(x){ return !x; }',
    compose: 'function() {\n  var functions = arguments;\n  return function() {\n    var i, result;\n    result = functions[0].apply(this, arguments);\n    for (i = 1; i < functions.length; ++i) {\n      result = functions[i](result);\n    }\n    return result;\n  };\n}',
    deepEq: 'function(x, y, type){\n  var toString = {}.toString, hasOwnProperty = {}.hasOwnProperty,\n      has = function (obj, key) { return hasOwnProperty.call(obj, key); };\n  var first = true;\n  return eq(x, y, []);\n  function eq(a, b, stack) {\n    var className, length, size, result, alength, blength, r, key, ref, sizeB;\n    if (a == null || b == null) { return a === b; }\n    if (a.__placeholder__ || b.__placeholder__) { return true; }\n    if (a === b) { return a !== 0 || 1 / a == 1 / b; }\n    className = toString.call(a);\n    if (toString.call(b) != className) { return false; }\n    switch (className) {\n      case \'[object String]\': return a == String(b);\n      case \'[object Number]\':\n        return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);\n      case \'[object Date]\':\n      case \'[object Boolean]\':\n        return +a == +b;\n      case \'[object RegExp]\':\n        return a.source == b.source &&\n               a.global == b.global &&\n               a.multiline == b.multiline &&\n               a.ignoreCase == b.ignoreCase;\n    }\n    if (typeof a != \'object\' || typeof b != \'object\') { return false; }\n    length = stack.length;\n    while (length--) { if (stack[length] == a) { return true; } }\n    stack.push(a);\n    size = 0;\n    result = true;\n    if (className == \'[object Array]\') {\n      alength = a.length;\n      blength = b.length;\n      if (first) {\n        switch (type) {\n        case \'===\': result = alength === blength; break;\n        case \'<==\': result = alength <= blength; break;\n        case \'<<=\': result = alength < blength; break;\n        }\n        size = alength;\n        first = false;\n      } else {\n        result = alength === blength;\n        size = alength;\n      }\n      if (result) {\n        while (size--) {\n          if (!(result = size in a == size in b && eq(a[size], b[size], stack))){ break; }\n        }\n      }\n    } else {\n      if (\'constructor\' in a != \'constructor\' in b || a.constructor != b.constructor) {\n        return false;\n      }\n      for (key in a) {\n        if (has(a, key)) {\n          size++;\n          if (!(result = has(b, key) && eq(a[key], b[key], stack))) { break; }\n        }\n      }\n      if (result) {\n        sizeB = 0;\n        for (key in b) {\n          if (has(b, key)) { ++sizeB; }\n        }\n        if (first) {\n          if (type === \'<<=\') {\n            result = size < sizeB;\n          } else if (type === \'<==\') {\n            result = size <= sizeB\n          } else {\n            result = size === sizeB;\n          }\n        } else {\n          first = false;\n          result = size === sizeB;\n        }\n      }\n    }\n    stack.pop();\n    return result;\n  }\n}',
    split: "''.split",
    replace: "''.replace",
    toString: '{}.toString',
    join: '[].join',
    slice: '[].slice',
    splice: '[].splice'
  };
  LEVEL_TOP = 0;
  LEVEL_PAREN = 1;
  LEVEL_LIST = 2;
  LEVEL_COND = 3;
  LEVEL_OP = 4;
  LEVEL_CALL = 5;
  (function() {
    this['&&'] = this['||'] = this['xor'] = 0.2;
    this['.&.'] = this['.^.'] = this['.|.'] = 0.3;
    this['=='] = this['!='] = this['~='] = this['!~='] = this['==='] = this['!=='] = 0.4;
    this['<'] = this['>'] = this['<='] = this['>='] = this.of = this['instanceof'] = 0.5;
    this['<<='] = this['>>='] = this['<=='] = this['>=='] = this['++'] = 0.5;
    this['.<<.'] = this['.>>.'] = this['.>>>.'] = 0.6;
    this['+'] = this['-'] = 0.7;
    this['*'] = this['/'] = this['%'] = 0.8;
  }.call(PREC = {unary: 0.9}));
  TAB = '  ';
  ID = /^(?!\d)[\w$\xAA-\uFFDC]+$/;
  SIMPLENUM = /^\d+$/;
  function util(it) {
    return Scope.root.assign(it + '$', UTILS[it]);
  }
  function entab(code, tab) {
    return code.replace(/\n/g, '\n' + tab);
  }
  function import$(obj, src) {
    var own = {}.hasOwnProperty;
    for (var key in src)
      if (own.call(src, key))
        obj[key] = src[key];
    return obj;
  }
  function clone$(it) {
    function fun() {}
    fun.prototype = it;
    return new fun;
  }
  function extend$(sub, sup) {
    function fun() {}
    fun.prototype = (sub.superclass = sup).prototype;
    (sub.prototype = new fun).constructor = sub;
    if (typeof sup.extended == 'function')
      sup.extended(sub);
    return sub;
  }
  function in$(x, xs) {
    var i = -1,
        l = xs.length >>> 0;
    while (++i < l)
      if (x === xs[i])
        return true;
    return false;
  }
  function repeatArray$(arr, n) {
    for (var r = []; n > 0; (n >>= 1) && (arr = arr.concat(arr)))
      if (n & 1)
        r.push.apply(r, arr);
    return r;
  }
  function repeatString$(str, n) {
    for (var r = ''; n > 0; (n >>= 1) && (str += str))
      if (n & 1)
        r += str;
    return r;
  }
  function importAll$(obj, src) {
    for (var key in src)
      obj[key] = src[key];
    return obj;
  }
  return module.exports;
});

$__System.registerDynamic("a", ["b", "c", "d", "e"], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  var base64VLQ = $__require('b');
  var util = $__require('c');
  var ArraySet = $__require('d').ArraySet;
  var MappingList = $__require('e').MappingList;
  function SourceMapGenerator(aArgs) {
    if (!aArgs) {
      aArgs = {};
    }
    this._file = util.getArg(aArgs, 'file', null);
    this._sourceRoot = util.getArg(aArgs, 'sourceRoot', null);
    this._skipValidation = util.getArg(aArgs, 'skipValidation', false);
    this._sources = new ArraySet();
    this._names = new ArraySet();
    this._mappings = new MappingList();
    this._sourcesContents = null;
  }
  SourceMapGenerator.prototype._version = 3;
  SourceMapGenerator.fromSourceMap = function SourceMapGenerator_fromSourceMap(aSourceMapConsumer) {
    var sourceRoot = aSourceMapConsumer.sourceRoot;
    var generator = new SourceMapGenerator({
      file: aSourceMapConsumer.file,
      sourceRoot: sourceRoot
    });
    aSourceMapConsumer.eachMapping(function(mapping) {
      var newMapping = {generated: {
          line: mapping.generatedLine,
          column: mapping.generatedColumn
        }};
      if (mapping.source != null) {
        newMapping.source = mapping.source;
        if (sourceRoot != null) {
          newMapping.source = util.relative(sourceRoot, newMapping.source);
        }
        newMapping.original = {
          line: mapping.originalLine,
          column: mapping.originalColumn
        };
        if (mapping.name != null) {
          newMapping.name = mapping.name;
        }
      }
      generator.addMapping(newMapping);
    });
    aSourceMapConsumer.sources.forEach(function(sourceFile) {
      var content = aSourceMapConsumer.sourceContentFor(sourceFile);
      if (content != null) {
        generator.setSourceContent(sourceFile, content);
      }
    });
    return generator;
  };
  SourceMapGenerator.prototype.addMapping = function SourceMapGenerator_addMapping(aArgs) {
    var generated = util.getArg(aArgs, 'generated');
    var original = util.getArg(aArgs, 'original', null);
    var source = util.getArg(aArgs, 'source', null);
    var name = util.getArg(aArgs, 'name', null);
    if (!this._skipValidation) {
      this._validateMapping(generated, original, source, name);
    }
    if (source != null) {
      source = String(source);
      if (!this._sources.has(source)) {
        this._sources.add(source);
      }
    }
    if (name != null) {
      name = String(name);
      if (!this._names.has(name)) {
        this._names.add(name);
      }
    }
    this._mappings.add({
      generatedLine: generated.line,
      generatedColumn: generated.column,
      originalLine: original != null && original.line,
      originalColumn: original != null && original.column,
      source: source,
      name: name
    });
  };
  SourceMapGenerator.prototype.setSourceContent = function SourceMapGenerator_setSourceContent(aSourceFile, aSourceContent) {
    var source = aSourceFile;
    if (this._sourceRoot != null) {
      source = util.relative(this._sourceRoot, source);
    }
    if (aSourceContent != null) {
      if (!this._sourcesContents) {
        this._sourcesContents = Object.create(null);
      }
      this._sourcesContents[util.toSetString(source)] = aSourceContent;
    } else if (this._sourcesContents) {
      delete this._sourcesContents[util.toSetString(source)];
      if (Object.keys(this._sourcesContents).length === 0) {
        this._sourcesContents = null;
      }
    }
  };
  SourceMapGenerator.prototype.applySourceMap = function SourceMapGenerator_applySourceMap(aSourceMapConsumer, aSourceFile, aSourceMapPath) {
    var sourceFile = aSourceFile;
    if (aSourceFile == null) {
      if (aSourceMapConsumer.file == null) {
        throw new Error('SourceMapGenerator.prototype.applySourceMap requires either an explicit source file, ' + 'or the source map\'s "file" property. Both were omitted.');
      }
      sourceFile = aSourceMapConsumer.file;
    }
    var sourceRoot = this._sourceRoot;
    if (sourceRoot != null) {
      sourceFile = util.relative(sourceRoot, sourceFile);
    }
    var newSources = new ArraySet();
    var newNames = new ArraySet();
    this._mappings.unsortedForEach(function(mapping) {
      if (mapping.source === sourceFile && mapping.originalLine != null) {
        var original = aSourceMapConsumer.originalPositionFor({
          line: mapping.originalLine,
          column: mapping.originalColumn
        });
        if (original.source != null) {
          mapping.source = original.source;
          if (aSourceMapPath != null) {
            mapping.source = util.join(aSourceMapPath, mapping.source);
          }
          if (sourceRoot != null) {
            mapping.source = util.relative(sourceRoot, mapping.source);
          }
          mapping.originalLine = original.line;
          mapping.originalColumn = original.column;
          if (original.name != null) {
            mapping.name = original.name;
          }
        }
      }
      var source = mapping.source;
      if (source != null && !newSources.has(source)) {
        newSources.add(source);
      }
      var name = mapping.name;
      if (name != null && !newNames.has(name)) {
        newNames.add(name);
      }
    }, this);
    this._sources = newSources;
    this._names = newNames;
    aSourceMapConsumer.sources.forEach(function(sourceFile) {
      var content = aSourceMapConsumer.sourceContentFor(sourceFile);
      if (content != null) {
        if (aSourceMapPath != null) {
          sourceFile = util.join(aSourceMapPath, sourceFile);
        }
        if (sourceRoot != null) {
          sourceFile = util.relative(sourceRoot, sourceFile);
        }
        this.setSourceContent(sourceFile, content);
      }
    }, this);
  };
  SourceMapGenerator.prototype._validateMapping = function SourceMapGenerator_validateMapping(aGenerated, aOriginal, aSource, aName) {
    if (aGenerated && 'line' in aGenerated && 'column' in aGenerated && aGenerated.line > 0 && aGenerated.column >= 0 && !aOriginal && !aSource && !aName) {
      return;
    } else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated && aOriginal && 'line' in aOriginal && 'column' in aOriginal && aGenerated.line > 0 && aGenerated.column >= 0 && aOriginal.line > 0 && aOriginal.column >= 0 && aSource) {
      return;
    } else {
      throw new Error('Invalid mapping: ' + JSON.stringify({
        generated: aGenerated,
        source: aSource,
        original: aOriginal,
        name: aName
      }));
    }
  };
  SourceMapGenerator.prototype._serializeMappings = function SourceMapGenerator_serializeMappings() {
    var previousGeneratedColumn = 0;
    var previousGeneratedLine = 1;
    var previousOriginalColumn = 0;
    var previousOriginalLine = 0;
    var previousName = 0;
    var previousSource = 0;
    var result = '';
    var next;
    var mapping;
    var nameIdx;
    var sourceIdx;
    var mappings = this._mappings.toArray();
    for (var i = 0,
        len = mappings.length; i < len; i++) {
      mapping = mappings[i];
      next = '';
      if (mapping.generatedLine !== previousGeneratedLine) {
        previousGeneratedColumn = 0;
        while (mapping.generatedLine !== previousGeneratedLine) {
          next += ';';
          previousGeneratedLine++;
        }
      } else {
        if (i > 0) {
          if (!util.compareByGeneratedPositionsInflated(mapping, mappings[i - 1])) {
            continue;
          }
          next += ',';
        }
      }
      next += base64VLQ.encode(mapping.generatedColumn - previousGeneratedColumn);
      previousGeneratedColumn = mapping.generatedColumn;
      if (mapping.source != null) {
        sourceIdx = this._sources.indexOf(mapping.source);
        next += base64VLQ.encode(sourceIdx - previousSource);
        previousSource = sourceIdx;
        next += base64VLQ.encode(mapping.originalLine - 1 - previousOriginalLine);
        previousOriginalLine = mapping.originalLine - 1;
        next += base64VLQ.encode(mapping.originalColumn - previousOriginalColumn);
        previousOriginalColumn = mapping.originalColumn;
        if (mapping.name != null) {
          nameIdx = this._names.indexOf(mapping.name);
          next += base64VLQ.encode(nameIdx - previousName);
          previousName = nameIdx;
        }
      }
      result += next;
    }
    return result;
  };
  SourceMapGenerator.prototype._generateSourcesContent = function SourceMapGenerator_generateSourcesContent(aSources, aSourceRoot) {
    return aSources.map(function(source) {
      if (!this._sourcesContents) {
        return null;
      }
      if (aSourceRoot != null) {
        source = util.relative(aSourceRoot, source);
      }
      var key = util.toSetString(source);
      return Object.prototype.hasOwnProperty.call(this._sourcesContents, key) ? this._sourcesContents[key] : null;
    }, this);
  };
  SourceMapGenerator.prototype.toJSON = function SourceMapGenerator_toJSON() {
    var map = {
      version: this._version,
      sources: this._sources.toArray(),
      names: this._names.toArray(),
      mappings: this._serializeMappings()
    };
    if (this._file != null) {
      map.file = this._file;
    }
    if (this._sourceRoot != null) {
      map.sourceRoot = this._sourceRoot;
    }
    if (this._sourcesContents) {
      map.sourcesContent = this._generateSourcesContent(map.sources, map.sourceRoot);
    }
    return map;
  };
  SourceMapGenerator.prototype.toString = function SourceMapGenerator_toString() {
    return JSON.stringify(this.toJSON());
  };
  exports.SourceMapGenerator = SourceMapGenerator;
  return module.exports;
});

$__System.registerDynamic("f", [], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  exports.GREATEST_LOWER_BOUND = 1;
  exports.LEAST_UPPER_BOUND = 2;
  function recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare, aBias) {
    var mid = Math.floor((aHigh - aLow) / 2) + aLow;
    var cmp = aCompare(aNeedle, aHaystack[mid], true);
    if (cmp === 0) {
      return mid;
    } else if (cmp > 0) {
      if (aHigh - mid > 1) {
        return recursiveSearch(mid, aHigh, aNeedle, aHaystack, aCompare, aBias);
      }
      if (aBias == exports.LEAST_UPPER_BOUND) {
        return aHigh < aHaystack.length ? aHigh : -1;
      } else {
        return mid;
      }
    } else {
      if (mid - aLow > 1) {
        return recursiveSearch(aLow, mid, aNeedle, aHaystack, aCompare, aBias);
      }
      if (aBias == exports.LEAST_UPPER_BOUND) {
        return mid;
      } else {
        return aLow < 0 ? -1 : aLow;
      }
    }
  }
  exports.search = function search(aNeedle, aHaystack, aCompare, aBias) {
    if (aHaystack.length === 0) {
      return -1;
    }
    var index = recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack, aCompare, aBias || exports.GREATEST_LOWER_BOUND);
    if (index < 0) {
      return -1;
    }
    while (index - 1 >= 0) {
      if (aCompare(aHaystack[index], aHaystack[index - 1], true) !== 0) {
        break;
      }
      --index;
    }
    return index;
  };
  return module.exports;
});

$__System.registerDynamic("10", [], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  function swap(ary, x, y) {
    var temp = ary[x];
    ary[x] = ary[y];
    ary[y] = temp;
  }
  function randomIntInRange(low, high) {
    return Math.round(low + (Math.random() * (high - low)));
  }
  function doQuickSort(ary, comparator, p, r) {
    if (p < r) {
      var pivotIndex = randomIntInRange(p, r);
      var i = p - 1;
      swap(ary, pivotIndex, r);
      var pivot = ary[r];
      for (var j = p; j < r; j++) {
        if (comparator(ary[j], pivot) <= 0) {
          i += 1;
          swap(ary, i, j);
        }
      }
      swap(ary, i + 1, j);
      var q = i + 1;
      doQuickSort(ary, comparator, p, q - 1);
      doQuickSort(ary, comparator, q + 1, r);
    }
  }
  exports.quickSort = function(ary, comparator) {
    doQuickSort(ary, comparator, 0, ary.length - 1);
  };
  return module.exports;
});

$__System.registerDynamic("11", ["c", "f", "d", "b", "10"], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  var util = $__require('c');
  var binarySearch = $__require('f');
  var ArraySet = $__require('d').ArraySet;
  var base64VLQ = $__require('b');
  var quickSort = $__require('10').quickSort;
  function SourceMapConsumer(aSourceMap) {
    var sourceMap = aSourceMap;
    if (typeof aSourceMap === 'string') {
      sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, ''));
    }
    return sourceMap.sections != null ? new IndexedSourceMapConsumer(sourceMap) : new BasicSourceMapConsumer(sourceMap);
  }
  SourceMapConsumer.fromSourceMap = function(aSourceMap) {
    return BasicSourceMapConsumer.fromSourceMap(aSourceMap);
  };
  SourceMapConsumer.prototype._version = 3;
  SourceMapConsumer.prototype.__generatedMappings = null;
  Object.defineProperty(SourceMapConsumer.prototype, '_generatedMappings', {get: function() {
      if (!this.__generatedMappings) {
        this._parseMappings(this._mappings, this.sourceRoot);
      }
      return this.__generatedMappings;
    }});
  SourceMapConsumer.prototype.__originalMappings = null;
  Object.defineProperty(SourceMapConsumer.prototype, '_originalMappings', {get: function() {
      if (!this.__originalMappings) {
        this._parseMappings(this._mappings, this.sourceRoot);
      }
      return this.__originalMappings;
    }});
  SourceMapConsumer.prototype._charIsMappingSeparator = function SourceMapConsumer_charIsMappingSeparator(aStr, index) {
    var c = aStr.charAt(index);
    return c === ";" || c === ",";
  };
  SourceMapConsumer.prototype._parseMappings = function SourceMapConsumer_parseMappings(aStr, aSourceRoot) {
    throw new Error("Subclasses must implement _parseMappings");
  };
  SourceMapConsumer.GENERATED_ORDER = 1;
  SourceMapConsumer.ORIGINAL_ORDER = 2;
  SourceMapConsumer.GREATEST_LOWER_BOUND = 1;
  SourceMapConsumer.LEAST_UPPER_BOUND = 2;
  SourceMapConsumer.prototype.eachMapping = function SourceMapConsumer_eachMapping(aCallback, aContext, aOrder) {
    var context = aContext || null;
    var order = aOrder || SourceMapConsumer.GENERATED_ORDER;
    var mappings;
    switch (order) {
      case SourceMapConsumer.GENERATED_ORDER:
        mappings = this._generatedMappings;
        break;
      case SourceMapConsumer.ORIGINAL_ORDER:
        mappings = this._originalMappings;
        break;
      default:
        throw new Error("Unknown order of iteration.");
    }
    var sourceRoot = this.sourceRoot;
    mappings.map(function(mapping) {
      var source = mapping.source === null ? null : this._sources.at(mapping.source);
      if (source != null && sourceRoot != null) {
        source = util.join(sourceRoot, source);
      }
      return {
        source: source,
        generatedLine: mapping.generatedLine,
        generatedColumn: mapping.generatedColumn,
        originalLine: mapping.originalLine,
        originalColumn: mapping.originalColumn,
        name: mapping.name === null ? null : this._names.at(mapping.name)
      };
    }, this).forEach(aCallback, context);
  };
  SourceMapConsumer.prototype.allGeneratedPositionsFor = function SourceMapConsumer_allGeneratedPositionsFor(aArgs) {
    var line = util.getArg(aArgs, 'line');
    var needle = {
      source: util.getArg(aArgs, 'source'),
      originalLine: line,
      originalColumn: util.getArg(aArgs, 'column', 0)
    };
    if (this.sourceRoot != null) {
      needle.source = util.relative(this.sourceRoot, needle.source);
    }
    if (!this._sources.has(needle.source)) {
      return [];
    }
    needle.source = this._sources.indexOf(needle.source);
    var mappings = [];
    var index = this._findMapping(needle, this._originalMappings, "originalLine", "originalColumn", util.compareByOriginalPositions, binarySearch.LEAST_UPPER_BOUND);
    if (index >= 0) {
      var mapping = this._originalMappings[index];
      if (aArgs.column === undefined) {
        var originalLine = mapping.originalLine;
        while (mapping && mapping.originalLine === originalLine) {
          mappings.push({
            line: util.getArg(mapping, 'generatedLine', null),
            column: util.getArg(mapping, 'generatedColumn', null),
            lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null)
          });
          mapping = this._originalMappings[++index];
        }
      } else {
        var originalColumn = mapping.originalColumn;
        while (mapping && mapping.originalLine === line && mapping.originalColumn == originalColumn) {
          mappings.push({
            line: util.getArg(mapping, 'generatedLine', null),
            column: util.getArg(mapping, 'generatedColumn', null),
            lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null)
          });
          mapping = this._originalMappings[++index];
        }
      }
    }
    return mappings;
  };
  exports.SourceMapConsumer = SourceMapConsumer;
  function BasicSourceMapConsumer(aSourceMap) {
    var sourceMap = aSourceMap;
    if (typeof aSourceMap === 'string') {
      sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, ''));
    }
    var version = util.getArg(sourceMap, 'version');
    var sources = util.getArg(sourceMap, 'sources');
    var names = util.getArg(sourceMap, 'names', []);
    var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null);
    var sourcesContent = util.getArg(sourceMap, 'sourcesContent', null);
    var mappings = util.getArg(sourceMap, 'mappings');
    var file = util.getArg(sourceMap, 'file', null);
    if (version != this._version) {
      throw new Error('Unsupported version: ' + version);
    }
    sources = sources.map(String).map(util.normalize).map(function(source) {
      return sourceRoot && util.isAbsolute(sourceRoot) && util.isAbsolute(source) ? util.relative(sourceRoot, source) : source;
    });
    this._names = ArraySet.fromArray(names.map(String), true);
    this._sources = ArraySet.fromArray(sources, true);
    this.sourceRoot = sourceRoot;
    this.sourcesContent = sourcesContent;
    this._mappings = mappings;
    this.file = file;
  }
  BasicSourceMapConsumer.prototype = Object.create(SourceMapConsumer.prototype);
  BasicSourceMapConsumer.prototype.consumer = SourceMapConsumer;
  BasicSourceMapConsumer.fromSourceMap = function SourceMapConsumer_fromSourceMap(aSourceMap) {
    var smc = Object.create(BasicSourceMapConsumer.prototype);
    var names = smc._names = ArraySet.fromArray(aSourceMap._names.toArray(), true);
    var sources = smc._sources = ArraySet.fromArray(aSourceMap._sources.toArray(), true);
    smc.sourceRoot = aSourceMap._sourceRoot;
    smc.sourcesContent = aSourceMap._generateSourcesContent(smc._sources.toArray(), smc.sourceRoot);
    smc.file = aSourceMap._file;
    var generatedMappings = aSourceMap._mappings.toArray().slice();
    var destGeneratedMappings = smc.__generatedMappings = [];
    var destOriginalMappings = smc.__originalMappings = [];
    for (var i = 0,
        length = generatedMappings.length; i < length; i++) {
      var srcMapping = generatedMappings[i];
      var destMapping = new Mapping;
      destMapping.generatedLine = srcMapping.generatedLine;
      destMapping.generatedColumn = srcMapping.generatedColumn;
      if (srcMapping.source) {
        destMapping.source = sources.indexOf(srcMapping.source);
        destMapping.originalLine = srcMapping.originalLine;
        destMapping.originalColumn = srcMapping.originalColumn;
        if (srcMapping.name) {
          destMapping.name = names.indexOf(srcMapping.name);
        }
        destOriginalMappings.push(destMapping);
      }
      destGeneratedMappings.push(destMapping);
    }
    quickSort(smc.__originalMappings, util.compareByOriginalPositions);
    return smc;
  };
  BasicSourceMapConsumer.prototype._version = 3;
  Object.defineProperty(BasicSourceMapConsumer.prototype, 'sources', {get: function() {
      return this._sources.toArray().map(function(s) {
        return this.sourceRoot != null ? util.join(this.sourceRoot, s) : s;
      }, this);
    }});
  function Mapping() {
    this.generatedLine = 0;
    this.generatedColumn = 0;
    this.source = null;
    this.originalLine = null;
    this.originalColumn = null;
    this.name = null;
  }
  BasicSourceMapConsumer.prototype._parseMappings = function SourceMapConsumer_parseMappings(aStr, aSourceRoot) {
    var generatedLine = 1;
    var previousGeneratedColumn = 0;
    var previousOriginalLine = 0;
    var previousOriginalColumn = 0;
    var previousSource = 0;
    var previousName = 0;
    var length = aStr.length;
    var index = 0;
    var cachedSegments = {};
    var temp = {};
    var originalMappings = [];
    var generatedMappings = [];
    var mapping,
        str,
        segment,
        end,
        value;
    while (index < length) {
      if (aStr.charAt(index) === ';') {
        generatedLine++;
        index++;
        previousGeneratedColumn = 0;
      } else if (aStr.charAt(index) === ',') {
        index++;
      } else {
        mapping = new Mapping();
        mapping.generatedLine = generatedLine;
        for (end = index; end < length; end++) {
          if (this._charIsMappingSeparator(aStr, end)) {
            break;
          }
        }
        str = aStr.slice(index, end);
        segment = cachedSegments[str];
        if (segment) {
          index += str.length;
        } else {
          segment = [];
          while (index < end) {
            base64VLQ.decode(aStr, index, temp);
            value = temp.value;
            index = temp.rest;
            segment.push(value);
          }
          if (segment.length === 2) {
            throw new Error('Found a source, but no line and column');
          }
          if (segment.length === 3) {
            throw new Error('Found a source and line, but no column');
          }
          cachedSegments[str] = segment;
        }
        mapping.generatedColumn = previousGeneratedColumn + segment[0];
        previousGeneratedColumn = mapping.generatedColumn;
        if (segment.length > 1) {
          mapping.source = previousSource + segment[1];
          previousSource += segment[1];
          mapping.originalLine = previousOriginalLine + segment[2];
          previousOriginalLine = mapping.originalLine;
          mapping.originalLine += 1;
          mapping.originalColumn = previousOriginalColumn + segment[3];
          previousOriginalColumn = mapping.originalColumn;
          if (segment.length > 4) {
            mapping.name = previousName + segment[4];
            previousName += segment[4];
          }
        }
        generatedMappings.push(mapping);
        if (typeof mapping.originalLine === 'number') {
          originalMappings.push(mapping);
        }
      }
    }
    quickSort(generatedMappings, util.compareByGeneratedPositionsDeflated);
    this.__generatedMappings = generatedMappings;
    quickSort(originalMappings, util.compareByOriginalPositions);
    this.__originalMappings = originalMappings;
  };
  BasicSourceMapConsumer.prototype._findMapping = function SourceMapConsumer_findMapping(aNeedle, aMappings, aLineName, aColumnName, aComparator, aBias) {
    if (aNeedle[aLineName] <= 0) {
      throw new TypeError('Line must be greater than or equal to 1, got ' + aNeedle[aLineName]);
    }
    if (aNeedle[aColumnName] < 0) {
      throw new TypeError('Column must be greater than or equal to 0, got ' + aNeedle[aColumnName]);
    }
    return binarySearch.search(aNeedle, aMappings, aComparator, aBias);
  };
  BasicSourceMapConsumer.prototype.computeColumnSpans = function SourceMapConsumer_computeColumnSpans() {
    for (var index = 0; index < this._generatedMappings.length; ++index) {
      var mapping = this._generatedMappings[index];
      if (index + 1 < this._generatedMappings.length) {
        var nextMapping = this._generatedMappings[index + 1];
        if (mapping.generatedLine === nextMapping.generatedLine) {
          mapping.lastGeneratedColumn = nextMapping.generatedColumn - 1;
          continue;
        }
      }
      mapping.lastGeneratedColumn = Infinity;
    }
  };
  BasicSourceMapConsumer.prototype.originalPositionFor = function SourceMapConsumer_originalPositionFor(aArgs) {
    var needle = {
      generatedLine: util.getArg(aArgs, 'line'),
      generatedColumn: util.getArg(aArgs, 'column')
    };
    var index = this._findMapping(needle, this._generatedMappings, "generatedLine", "generatedColumn", util.compareByGeneratedPositionsDeflated, util.getArg(aArgs, 'bias', SourceMapConsumer.GREATEST_LOWER_BOUND));
    if (index >= 0) {
      var mapping = this._generatedMappings[index];
      if (mapping.generatedLine === needle.generatedLine) {
        var source = util.getArg(mapping, 'source', null);
        if (source !== null) {
          source = this._sources.at(source);
          if (this.sourceRoot != null) {
            source = util.join(this.sourceRoot, source);
          }
        }
        var name = util.getArg(mapping, 'name', null);
        if (name !== null) {
          name = this._names.at(name);
        }
        return {
          source: source,
          line: util.getArg(mapping, 'originalLine', null),
          column: util.getArg(mapping, 'originalColumn', null),
          name: name
        };
      }
    }
    return {
      source: null,
      line: null,
      column: null,
      name: null
    };
  };
  BasicSourceMapConsumer.prototype.hasContentsOfAllSources = function BasicSourceMapConsumer_hasContentsOfAllSources() {
    if (!this.sourcesContent) {
      return false;
    }
    return this.sourcesContent.length >= this._sources.size() && !this.sourcesContent.some(function(sc) {
      return sc == null;
    });
  };
  BasicSourceMapConsumer.prototype.sourceContentFor = function SourceMapConsumer_sourceContentFor(aSource, nullOnMissing) {
    if (!this.sourcesContent) {
      return null;
    }
    if (this.sourceRoot != null) {
      aSource = util.relative(this.sourceRoot, aSource);
    }
    if (this._sources.has(aSource)) {
      return this.sourcesContent[this._sources.indexOf(aSource)];
    }
    var url;
    if (this.sourceRoot != null && (url = util.urlParse(this.sourceRoot))) {
      var fileUriAbsPath = aSource.replace(/^file:\/\//, "");
      if (url.scheme == "file" && this._sources.has(fileUriAbsPath)) {
        return this.sourcesContent[this._sources.indexOf(fileUriAbsPath)];
      }
      if ((!url.path || url.path == "/") && this._sources.has("/" + aSource)) {
        return this.sourcesContent[this._sources.indexOf("/" + aSource)];
      }
    }
    if (nullOnMissing) {
      return null;
    } else {
      throw new Error('"' + aSource + '" is not in the SourceMap.');
    }
  };
  BasicSourceMapConsumer.prototype.generatedPositionFor = function SourceMapConsumer_generatedPositionFor(aArgs) {
    var source = util.getArg(aArgs, 'source');
    if (this.sourceRoot != null) {
      source = util.relative(this.sourceRoot, source);
    }
    if (!this._sources.has(source)) {
      return {
        line: null,
        column: null,
        lastColumn: null
      };
    }
    source = this._sources.indexOf(source);
    var needle = {
      source: source,
      originalLine: util.getArg(aArgs, 'line'),
      originalColumn: util.getArg(aArgs, 'column')
    };
    var index = this._findMapping(needle, this._originalMappings, "originalLine", "originalColumn", util.compareByOriginalPositions, util.getArg(aArgs, 'bias', SourceMapConsumer.GREATEST_LOWER_BOUND));
    if (index >= 0) {
      var mapping = this._originalMappings[index];
      if (mapping.source === needle.source) {
        return {
          line: util.getArg(mapping, 'generatedLine', null),
          column: util.getArg(mapping, 'generatedColumn', null),
          lastColumn: util.getArg(mapping, 'lastGeneratedColumn', null)
        };
      }
    }
    return {
      line: null,
      column: null,
      lastColumn: null
    };
  };
  exports.BasicSourceMapConsumer = BasicSourceMapConsumer;
  function IndexedSourceMapConsumer(aSourceMap) {
    var sourceMap = aSourceMap;
    if (typeof aSourceMap === 'string') {
      sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, ''));
    }
    var version = util.getArg(sourceMap, 'version');
    var sections = util.getArg(sourceMap, 'sections');
    if (version != this._version) {
      throw new Error('Unsupported version: ' + version);
    }
    this._sources = new ArraySet();
    this._names = new ArraySet();
    var lastOffset = {
      line: -1,
      column: 0
    };
    this._sections = sections.map(function(s) {
      if (s.url) {
        throw new Error('Support for url field in sections not implemented.');
      }
      var offset = util.getArg(s, 'offset');
      var offsetLine = util.getArg(offset, 'line');
      var offsetColumn = util.getArg(offset, 'column');
      if (offsetLine < lastOffset.line || (offsetLine === lastOffset.line && offsetColumn < lastOffset.column)) {
        throw new Error('Section offsets must be ordered and non-overlapping.');
      }
      lastOffset = offset;
      return {
        generatedOffset: {
          generatedLine: offsetLine + 1,
          generatedColumn: offsetColumn + 1
        },
        consumer: new SourceMapConsumer(util.getArg(s, 'map'))
      };
    });
  }
  IndexedSourceMapConsumer.prototype = Object.create(SourceMapConsumer.prototype);
  IndexedSourceMapConsumer.prototype.constructor = SourceMapConsumer;
  IndexedSourceMapConsumer.prototype._version = 3;
  Object.defineProperty(IndexedSourceMapConsumer.prototype, 'sources', {get: function() {
      var sources = [];
      for (var i = 0; i < this._sections.length; i++) {
        for (var j = 0; j < this._sections[i].consumer.sources.length; j++) {
          sources.push(this._sections[i].consumer.sources[j]);
        }
      }
      return sources;
    }});
  IndexedSourceMapConsumer.prototype.originalPositionFor = function IndexedSourceMapConsumer_originalPositionFor(aArgs) {
    var needle = {
      generatedLine: util.getArg(aArgs, 'line'),
      generatedColumn: util.getArg(aArgs, 'column')
    };
    var sectionIndex = binarySearch.search(needle, this._sections, function(needle, section) {
      var cmp = needle.generatedLine - section.generatedOffset.generatedLine;
      if (cmp) {
        return cmp;
      }
      return (needle.generatedColumn - section.generatedOffset.generatedColumn);
    });
    var section = this._sections[sectionIndex];
    if (!section) {
      return {
        source: null,
        line: null,
        column: null,
        name: null
      };
    }
    return section.consumer.originalPositionFor({
      line: needle.generatedLine - (section.generatedOffset.generatedLine - 1),
      column: needle.generatedColumn - (section.generatedOffset.generatedLine === needle.generatedLine ? section.generatedOffset.generatedColumn - 1 : 0),
      bias: aArgs.bias
    });
  };
  IndexedSourceMapConsumer.prototype.hasContentsOfAllSources = function IndexedSourceMapConsumer_hasContentsOfAllSources() {
    return this._sections.every(function(s) {
      return s.consumer.hasContentsOfAllSources();
    });
  };
  IndexedSourceMapConsumer.prototype.sourceContentFor = function IndexedSourceMapConsumer_sourceContentFor(aSource, nullOnMissing) {
    for (var i = 0; i < this._sections.length; i++) {
      var section = this._sections[i];
      var content = section.consumer.sourceContentFor(aSource, true);
      if (content) {
        return content;
      }
    }
    if (nullOnMissing) {
      return null;
    } else {
      throw new Error('"' + aSource + '" is not in the SourceMap.');
    }
  };
  IndexedSourceMapConsumer.prototype.generatedPositionFor = function IndexedSourceMapConsumer_generatedPositionFor(aArgs) {
    for (var i = 0; i < this._sections.length; i++) {
      var section = this._sections[i];
      if (section.consumer.sources.indexOf(util.getArg(aArgs, 'source')) === -1) {
        continue;
      }
      var generatedPosition = section.consumer.generatedPositionFor(aArgs);
      if (generatedPosition) {
        var ret = {
          line: generatedPosition.line + (section.generatedOffset.generatedLine - 1),
          column: generatedPosition.column + (section.generatedOffset.generatedLine === generatedPosition.line ? section.generatedOffset.generatedColumn - 1 : 0)
        };
        return ret;
      }
    }
    return {
      line: null,
      column: null
    };
  };
  IndexedSourceMapConsumer.prototype._parseMappings = function IndexedSourceMapConsumer_parseMappings(aStr, aSourceRoot) {
    this.__generatedMappings = [];
    this.__originalMappings = [];
    for (var i = 0; i < this._sections.length; i++) {
      var section = this._sections[i];
      var sectionMappings = section.consumer._generatedMappings;
      for (var j = 0; j < sectionMappings.length; j++) {
        var mapping = sectionMappings[j];
        var source = section.consumer._sources.at(mapping.source);
        if (section.consumer.sourceRoot !== null) {
          source = util.join(section.consumer.sourceRoot, source);
        }
        this._sources.add(source);
        source = this._sources.indexOf(source);
        var name = section.consumer._names.at(mapping.name);
        this._names.add(name);
        name = this._names.indexOf(name);
        var adjustedMapping = {
          source: source,
          generatedLine: mapping.generatedLine + (section.generatedOffset.generatedLine - 1),
          generatedColumn: mapping.generatedColumn + (section.generatedOffset.generatedLine === mapping.generatedLine ? section.generatedOffset.generatedColumn - 1 : 0),
          originalLine: mapping.originalLine,
          originalColumn: mapping.originalColumn,
          name: name
        };
        this.__generatedMappings.push(adjustedMapping);
        if (typeof adjustedMapping.originalLine === 'number') {
          this.__originalMappings.push(adjustedMapping);
        }
      }
    }
    quickSort(this.__generatedMappings, util.compareByGeneratedPositionsDeflated);
    quickSort(this.__originalMappings, util.compareByOriginalPositions);
  };
  exports.IndexedSourceMapConsumer = IndexedSourceMapConsumer;
  return module.exports;
});

$__System.registerDynamic("12", [], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  var intToCharMap = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split('');
  exports.encode = function(number) {
    if (0 <= number && number < intToCharMap.length) {
      return intToCharMap[number];
    }
    throw new TypeError("Must be between 0 and 63: " + number);
  };
  exports.decode = function(charCode) {
    var bigA = 65;
    var bigZ = 90;
    var littleA = 97;
    var littleZ = 122;
    var zero = 48;
    var nine = 57;
    var plus = 43;
    var slash = 47;
    var littleOffset = 26;
    var numberOffset = 52;
    if (bigA <= charCode && charCode <= bigZ) {
      return (charCode - bigA);
    }
    if (littleA <= charCode && charCode <= littleZ) {
      return (charCode - littleA + littleOffset);
    }
    if (zero <= charCode && charCode <= nine) {
      return (charCode - zero + numberOffset);
    }
    if (charCode == plus) {
      return 62;
    }
    if (charCode == slash) {
      return 63;
    }
    return -1;
  };
  return module.exports;
});

$__System.registerDynamic("b", ["12"], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  var base64 = $__require('12');
  var VLQ_BASE_SHIFT = 5;
  var VLQ_BASE = 1 << VLQ_BASE_SHIFT;
  var VLQ_BASE_MASK = VLQ_BASE - 1;
  var VLQ_CONTINUATION_BIT = VLQ_BASE;
  function toVLQSigned(aValue) {
    return aValue < 0 ? ((-aValue) << 1) + 1 : (aValue << 1) + 0;
  }
  function fromVLQSigned(aValue) {
    var isNegative = (aValue & 1) === 1;
    var shifted = aValue >> 1;
    return isNegative ? -shifted : shifted;
  }
  exports.encode = function base64VLQ_encode(aValue) {
    var encoded = "";
    var digit;
    var vlq = toVLQSigned(aValue);
    do {
      digit = vlq & VLQ_BASE_MASK;
      vlq >>>= VLQ_BASE_SHIFT;
      if (vlq > 0) {
        digit |= VLQ_CONTINUATION_BIT;
      }
      encoded += base64.encode(digit);
    } while (vlq > 0);
    return encoded;
  };
  exports.decode = function base64VLQ_decode(aStr, aIndex, aOutParam) {
    var strLen = aStr.length;
    var result = 0;
    var shift = 0;
    var continuation,
        digit;
    do {
      if (aIndex >= strLen) {
        throw new Error("Expected more digits in base 64 VLQ value.");
      }
      digit = base64.decode(aStr.charCodeAt(aIndex++));
      if (digit === -1) {
        throw new Error("Invalid base64 digit: " + aStr.charAt(aIndex - 1));
      }
      continuation = !!(digit & VLQ_CONTINUATION_BIT);
      digit &= VLQ_BASE_MASK;
      result = result + (digit << shift);
      shift += VLQ_BASE_SHIFT;
    } while (continuation);
    aOutParam.value = fromVLQSigned(result);
    aOutParam.rest = aIndex;
  };
  return module.exports;
});

$__System.registerDynamic("d", ["c"], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  var util = $__require('c');
  var has = Object.prototype.hasOwnProperty;
  function ArraySet() {
    this._array = [];
    this._set = Object.create(null);
  }
  ArraySet.fromArray = function ArraySet_fromArray(aArray, aAllowDuplicates) {
    var set = new ArraySet();
    for (var i = 0,
        len = aArray.length; i < len; i++) {
      set.add(aArray[i], aAllowDuplicates);
    }
    return set;
  };
  ArraySet.prototype.size = function ArraySet_size() {
    return Object.getOwnPropertyNames(this._set).length;
  };
  ArraySet.prototype.add = function ArraySet_add(aStr, aAllowDuplicates) {
    var sStr = util.toSetString(aStr);
    var isDuplicate = has.call(this._set, sStr);
    var idx = this._array.length;
    if (!isDuplicate || aAllowDuplicates) {
      this._array.push(aStr);
    }
    if (!isDuplicate) {
      this._set[sStr] = idx;
    }
  };
  ArraySet.prototype.has = function ArraySet_has(aStr) {
    var sStr = util.toSetString(aStr);
    return has.call(this._set, sStr);
  };
  ArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) {
    var sStr = util.toSetString(aStr);
    if (has.call(this._set, sStr)) {
      return this._set[sStr];
    }
    throw new Error('"' + aStr + '" is not in the set.');
  };
  ArraySet.prototype.at = function ArraySet_at(aIdx) {
    if (aIdx >= 0 && aIdx < this._array.length) {
      return this._array[aIdx];
    }
    throw new Error('No element indexed by ' + aIdx);
  };
  ArraySet.prototype.toArray = function ArraySet_toArray() {
    return this._array.slice();
  };
  exports.ArraySet = ArraySet;
  return module.exports;
});

$__System.registerDynamic("e", ["c"], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  var util = $__require('c');
  function generatedPositionAfter(mappingA, mappingB) {
    var lineA = mappingA.generatedLine;
    var lineB = mappingB.generatedLine;
    var columnA = mappingA.generatedColumn;
    var columnB = mappingB.generatedColumn;
    return lineB > lineA || lineB == lineA && columnB >= columnA || util.compareByGeneratedPositionsInflated(mappingA, mappingB) <= 0;
  }
  function MappingList() {
    this._array = [];
    this._sorted = true;
    this._last = {
      generatedLine: -1,
      generatedColumn: 0
    };
  }
  MappingList.prototype.unsortedForEach = function MappingList_forEach(aCallback, aThisArg) {
    this._array.forEach(aCallback, aThisArg);
  };
  MappingList.prototype.add = function MappingList_add(aMapping) {
    if (generatedPositionAfter(this._last, aMapping)) {
      this._last = aMapping;
      this._array.push(aMapping);
    } else {
      this._sorted = false;
      this._array.push(aMapping);
    }
  };
  MappingList.prototype.toArray = function MappingList_toArray() {
    if (!this._sorted) {
      this._array.sort(util.compareByGeneratedPositionsInflated);
      this._sorted = true;
    }
    return this._array;
  };
  exports.MappingList = MappingList;
  return module.exports;
});

$__System.register("13", [], function() { return { setters: [], execute: function() {} } });

$__System.registerDynamic("c", [], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  function getArg(aArgs, aName, aDefaultValue) {
    if (aName in aArgs) {
      return aArgs[aName];
    } else if (arguments.length === 3) {
      return aDefaultValue;
    } else {
      throw new Error('"' + aName + '" is a required argument.');
    }
  }
  exports.getArg = getArg;
  var urlRegexp = /^(?:([\w+\-.]+):)?\/\/(?:(\w+:\w+)@)?([\w.]*)(?::(\d+))?(\S*)$/;
  var dataUrlRegexp = /^data:.+\,.+$/;
  function urlParse(aUrl) {
    var match = aUrl.match(urlRegexp);
    if (!match) {
      return null;
    }
    return {
      scheme: match[1],
      auth: match[2],
      host: match[3],
      port: match[4],
      path: match[5]
    };
  }
  exports.urlParse = urlParse;
  function urlGenerate(aParsedUrl) {
    var url = '';
    if (aParsedUrl.scheme) {
      url += aParsedUrl.scheme + ':';
    }
    url += '//';
    if (aParsedUrl.auth) {
      url += aParsedUrl.auth + '@';
    }
    if (aParsedUrl.host) {
      url += aParsedUrl.host;
    }
    if (aParsedUrl.port) {
      url += ":" + aParsedUrl.port;
    }
    if (aParsedUrl.path) {
      url += aParsedUrl.path;
    }
    return url;
  }
  exports.urlGenerate = urlGenerate;
  function normalize(aPath) {
    var path = aPath;
    var url = urlParse(aPath);
    if (url) {
      if (!url.path) {
        return aPath;
      }
      path = url.path;
    }
    var isAbsolute = exports.isAbsolute(path);
    var parts = path.split(/\/+/);
    for (var part,
        up = 0,
        i = parts.length - 1; i >= 0; i--) {
      part = parts[i];
      if (part === '.') {
        parts.splice(i, 1);
      } else if (part === '..') {
        up++;
      } else if (up > 0) {
        if (part === '') {
          parts.splice(i + 1, up);
          up = 0;
        } else {
          parts.splice(i, 2);
          up--;
        }
      }
    }
    path = parts.join('/');
    if (path === '') {
      path = isAbsolute ? '/' : '.';
    }
    if (url) {
      url.path = path;
      return urlGenerate(url);
    }
    return path;
  }
  exports.normalize = normalize;
  function join(aRoot, aPath) {
    if (aRoot === "") {
      aRoot = ".";
    }
    if (aPath === "") {
      aPath = ".";
    }
    var aPathUrl = urlParse(aPath);
    var aRootUrl = urlParse(aRoot);
    if (aRootUrl) {
      aRoot = aRootUrl.path || '/';
    }
    if (aPathUrl && !aPathUrl.scheme) {
      if (aRootUrl) {
        aPathUrl.scheme = aRootUrl.scheme;
      }
      return urlGenerate(aPathUrl);
    }
    if (aPathUrl || aPath.match(dataUrlRegexp)) {
      return aPath;
    }
    if (aRootUrl && !aRootUrl.host && !aRootUrl.path) {
      aRootUrl.host = aPath;
      return urlGenerate(aRootUrl);
    }
    var joined = aPath.charAt(0) === '/' ? aPath : normalize(aRoot.replace(/\/+$/, '') + '/' + aPath);
    if (aRootUrl) {
      aRootUrl.path = joined;
      return urlGenerate(aRootUrl);
    }
    return joined;
  }
  exports.join = join;
  exports.isAbsolute = function(aPath) {
    return aPath.charAt(0) === '/' || !!aPath.match(urlRegexp);
  };
  function relative(aRoot, aPath) {
    if (aRoot === "") {
      aRoot = ".";
    }
    aRoot = aRoot.replace(/\/$/, '');
    var level = 0;
    while (aPath.indexOf(aRoot + '/') !== 0) {
      var index = aRoot.lastIndexOf("/");
      if (index < 0) {
        return aPath;
      }
      aRoot = aRoot.slice(0, index);
      if (aRoot.match(/^([^\/]+:\/)?\/*$/)) {
        return aPath;
      }
      ++level;
    }
    return Array(level + 1).join("../") + aPath.substr(aRoot.length + 1);
  }
  exports.relative = relative;
  var supportsNullProto = (function() {
    var obj = Object.create(null);
    return !('__proto__' in obj);
  }());
  function identity(s) {
    return s;
  }
  function toSetString(aStr) {
    if (isProtoString(aStr)) {
      return '$' + aStr;
    }
    return aStr;
  }
  exports.toSetString = supportsNullProto ? identity : toSetString;
  function fromSetString(aStr) {
    if (isProtoString(aStr)) {
      return aStr.slice(1);
    }
    return aStr;
  }
  exports.fromSetString = supportsNullProto ? identity : fromSetString;
  function isProtoString(s) {
    if (!s) {
      return false;
    }
    var length = s.length;
    if (length < 9) {
      return false;
    }
    if (s.charCodeAt(length - 1) !== 95 || s.charCodeAt(length - 2) !== 95 || s.charCodeAt(length - 3) !== 111 || s.charCodeAt(length - 4) !== 116 || s.charCodeAt(length - 5) !== 111 || s.charCodeAt(length - 6) !== 114 || s.charCodeAt(length - 7) !== 112 || s.charCodeAt(length - 8) !== 95 || s.charCodeAt(length - 9) !== 95) {
      return false;
    }
    for (var i = length - 10; i >= 0; i--) {
      if (s.charCodeAt(i) !== 36) {
        return false;
      }
    }
    return true;
  }
  function compareByOriginalPositions(mappingA, mappingB, onlyCompareOriginal) {
    var cmp = mappingA.source - mappingB.source;
    if (cmp !== 0) {
      return cmp;
    }
    cmp = mappingA.originalLine - mappingB.originalLine;
    if (cmp !== 0) {
      return cmp;
    }
    cmp = mappingA.originalColumn - mappingB.originalColumn;
    if (cmp !== 0 || onlyCompareOriginal) {
      return cmp;
    }
    cmp = mappingA.generatedColumn - mappingB.generatedColumn;
    if (cmp !== 0) {
      return cmp;
    }
    cmp = mappingA.generatedLine - mappingB.generatedLine;
    if (cmp !== 0) {
      return cmp;
    }
    return mappingA.name - mappingB.name;
  }
  exports.compareByOriginalPositions = compareByOriginalPositions;
  function compareByGeneratedPositionsDeflated(mappingA, mappingB, onlyCompareGenerated) {
    var cmp = mappingA.generatedLine - mappingB.generatedLine;
    if (cmp !== 0) {
      return cmp;
    }
    cmp = mappingA.generatedColumn - mappingB.generatedColumn;
    if (cmp !== 0 || onlyCompareGenerated) {
      return cmp;
    }
    cmp = mappingA.source - mappingB.source;
    if (cmp !== 0) {
      return cmp;
    }
    cmp = mappingA.originalLine - mappingB.originalLine;
    if (cmp !== 0) {
      return cmp;
    }
    cmp = mappingA.originalColumn - mappingB.originalColumn;
    if (cmp !== 0) {
      return cmp;
    }
    return mappingA.name - mappingB.name;
  }
  exports.compareByGeneratedPositionsDeflated = compareByGeneratedPositionsDeflated;
  function strcmp(aStr1, aStr2) {
    if (aStr1 === aStr2) {
      return 0;
    }
    if (aStr1 > aStr2) {
      return 1;
    }
    return -1;
  }
  function compareByGeneratedPositionsInflated(mappingA, mappingB) {
    var cmp = mappingA.generatedLine - mappingB.generatedLine;
    if (cmp !== 0) {
      return cmp;
    }
    cmp = mappingA.generatedColumn - mappingB.generatedColumn;
    if (cmp !== 0) {
      return cmp;
    }
    cmp = strcmp(mappingA.source, mappingB.source);
    if (cmp !== 0) {
      return cmp;
    }
    cmp = mappingA.originalLine - mappingB.originalLine;
    if (cmp !== 0) {
      return cmp;
    }
    cmp = mappingA.originalColumn - mappingB.originalColumn;
    if (cmp !== 0) {
      return cmp;
    }
    return strcmp(mappingA.name, mappingB.name);
  }
  exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflated;
  return module.exports;
});

$__System.registerDynamic("14", ["13", "c"], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  var SourceMapGenerator = $__require('13').SourceMapGenerator;
  var util = $__require('c');
  var REGEX_NEWLINE = /(\r?\n)/;
  var NEWLINE_CODE = 10;
  var isSourceNode = "$$$isSourceNode$$$";
  function SourceNode(aLine, aColumn, aSource, aChunks, aName) {
    this.children = [];
    this.sourceContents = {};
    this.line = aLine == null ? null : aLine;
    this.column = aColumn == null ? null : aColumn;
    this.source = aSource == null ? null : aSource;
    this.name = aName == null ? null : aName;
    this[isSourceNode] = true;
    if (aChunks != null)
      this.add(aChunks);
  }
  SourceNode.fromStringWithSourceMap = function SourceNode_fromStringWithSourceMap(aGeneratedCode, aSourceMapConsumer, aRelativePath) {
    var node = new SourceNode();
    var remainingLines = aGeneratedCode.split(REGEX_NEWLINE);
    var shiftNextLine = function() {
      var lineContents = remainingLines.shift();
      var newLine = remainingLines.shift() || "";
      return lineContents + newLine;
    };
    var lastGeneratedLine = 1,
        lastGeneratedColumn = 0;
    var lastMapping = null;
    aSourceMapConsumer.eachMapping(function(mapping) {
      if (lastMapping !== null) {
        if (lastGeneratedLine < mapping.generatedLine) {
          addMappingWithCode(lastMapping, shiftNextLine());
          lastGeneratedLine++;
          lastGeneratedColumn = 0;
        } else {
          var nextLine = remainingLines[0];
          var code = nextLine.substr(0, mapping.generatedColumn - lastGeneratedColumn);
          remainingLines[0] = nextLine.substr(mapping.generatedColumn - lastGeneratedColumn);
          lastGeneratedColumn = mapping.generatedColumn;
          addMappingWithCode(lastMapping, code);
          lastMapping = mapping;
          return;
        }
      }
      while (lastGeneratedLine < mapping.generatedLine) {
        node.add(shiftNextLine());
        lastGeneratedLine++;
      }
      if (lastGeneratedColumn < mapping.generatedColumn) {
        var nextLine = remainingLines[0];
        node.add(nextLine.substr(0, mapping.generatedColumn));
        remainingLines[0] = nextLine.substr(mapping.generatedColumn);
        lastGeneratedColumn = mapping.generatedColumn;
      }
      lastMapping = mapping;
    }, this);
    if (remainingLines.length > 0) {
      if (lastMapping) {
        addMappingWithCode(lastMapping, shiftNextLine());
      }
      node.add(remainingLines.join(""));
    }
    aSourceMapConsumer.sources.forEach(function(sourceFile) {
      var content = aSourceMapConsumer.sourceContentFor(sourceFile);
      if (content != null) {
        if (aRelativePath != null) {
          sourceFile = util.join(aRelativePath, sourceFile);
        }
        node.setSourceContent(sourceFile, content);
      }
    });
    return node;
    function addMappingWithCode(mapping, code) {
      if (mapping === null || mapping.source === undefined) {
        node.add(code);
      } else {
        var source = aRelativePath ? util.join(aRelativePath, mapping.source) : mapping.source;
        node.add(new SourceNode(mapping.originalLine, mapping.originalColumn, source, code, mapping.name));
      }
    }
  };
  SourceNode.prototype.add = function SourceNode_add(aChunk) {
    if (Array.isArray(aChunk)) {
      aChunk.forEach(function(chunk) {
        this.add(chunk);
      }, this);
    } else if (aChunk[isSourceNode] || typeof aChunk === "string") {
      if (aChunk) {
        this.children.push(aChunk);
      }
    } else {
      throw new TypeError("Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk);
    }
    return this;
  };
  SourceNode.prototype.prepend = function SourceNode_prepend(aChunk) {
    if (Array.isArray(aChunk)) {
      for (var i = aChunk.length - 1; i >= 0; i--) {
        this.prepend(aChunk[i]);
      }
    } else if (aChunk[isSourceNode] || typeof aChunk === "string") {
      this.children.unshift(aChunk);
    } else {
      throw new TypeError("Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk);
    }
    return this;
  };
  SourceNode.prototype.walk = function SourceNode_walk(aFn) {
    var chunk;
    for (var i = 0,
        len = this.children.length; i < len; i++) {
      chunk = this.children[i];
      if (chunk[isSourceNode]) {
        chunk.walk(aFn);
      } else {
        if (chunk !== '') {
          aFn(chunk, {
            source: this.source,
            line: this.line,
            column: this.column,
            name: this.name
          });
        }
      }
    }
  };
  SourceNode.prototype.join = function SourceNode_join(aSep) {
    var newChildren;
    var i;
    var len = this.children.length;
    if (len > 0) {
      newChildren = [];
      for (i = 0; i < len - 1; i++) {
        newChildren.push(this.children[i]);
        newChildren.push(aSep);
      }
      newChildren.push(this.children[i]);
      this.children = newChildren;
    }
    return this;
  };
  SourceNode.prototype.replaceRight = function SourceNode_replaceRight(aPattern, aReplacement) {
    var lastChild = this.children[this.children.length - 1];
    if (lastChild[isSourceNode]) {
      lastChild.replaceRight(aPattern, aReplacement);
    } else if (typeof lastChild === 'string') {
      this.children[this.children.length - 1] = lastChild.replace(aPattern, aReplacement);
    } else {
      this.children.push(''.replace(aPattern, aReplacement));
    }
    return this;
  };
  SourceNode.prototype.setSourceContent = function SourceNode_setSourceContent(aSourceFile, aSourceContent) {
    this.sourceContents[util.toSetString(aSourceFile)] = aSourceContent;
  };
  SourceNode.prototype.walkSourceContents = function SourceNode_walkSourceContents(aFn) {
    for (var i = 0,
        len = this.children.length; i < len; i++) {
      if (this.children[i][isSourceNode]) {
        this.children[i].walkSourceContents(aFn);
      }
    }
    var sources = Object.keys(this.sourceContents);
    for (var i = 0,
        len = sources.length; i < len; i++) {
      aFn(util.fromSetString(sources[i]), this.sourceContents[sources[i]]);
    }
  };
  SourceNode.prototype.toString = function SourceNode_toString() {
    var str = "";
    this.walk(function(chunk) {
      str += chunk;
    });
    return str;
  };
  SourceNode.prototype.toStringWithSourceMap = function SourceNode_toStringWithSourceMap(aArgs) {
    var generated = {
      code: "",
      line: 1,
      column: 0
    };
    var map = new SourceMapGenerator(aArgs);
    var sourceMappingActive = false;
    var lastOriginalSource = null;
    var lastOriginalLine = null;
    var lastOriginalColumn = null;
    var lastOriginalName = null;
    this.walk(function(chunk, original) {
      generated.code += chunk;
      if (original.source !== null && original.line !== null && original.column !== null) {
        if (lastOriginalSource !== original.source || lastOriginalLine !== original.line || lastOriginalColumn !== original.column || lastOriginalName !== original.name) {
          map.addMapping({
            source: original.source,
            original: {
              line: original.line,
              column: original.column
            },
            generated: {
              line: generated.line,
              column: generated.column
            },
            name: original.name
          });
        }
        lastOriginalSource = original.source;
        lastOriginalLine = original.line;
        lastOriginalColumn = original.column;
        lastOriginalName = original.name;
        sourceMappingActive = true;
      } else if (sourceMappingActive) {
        map.addMapping({generated: {
            line: generated.line,
            column: generated.column
          }});
        lastOriginalSource = null;
        sourceMappingActive = false;
      }
      for (var idx = 0,
          length = chunk.length; idx < length; idx++) {
        if (chunk.charCodeAt(idx) === NEWLINE_CODE) {
          generated.line++;
          generated.column = 0;
          if (idx + 1 === length) {
            lastOriginalSource = null;
            sourceMappingActive = false;
          } else if (sourceMappingActive) {
            map.addMapping({
              source: original.source,
              original: {
                line: original.line,
                column: original.column
              },
              generated: {
                line: generated.line,
                column: generated.column
              },
              name: original.name
            });
          }
        } else {
          generated.column++;
        }
      }
    });
    this.walkSourceContents(function(sourceFile, sourceContent) {
      map.setSourceContent(sourceFile, sourceContent);
    });
    return {
      code: generated.code,
      map: map
    };
  };
  exports.SourceNode = SourceNode;
  return module.exports;
});

$__System.registerDynamic("9", ["a", "11", "14"], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  exports.SourceMapGenerator = $__require('a').SourceMapGenerator;
  exports.SourceMapConsumer = $__require('11').SourceMapConsumer;
  exports.SourceNode = $__require('14').SourceNode;
  return module.exports;
});

$__System.registerDynamic("4", [], false, function($__require, $__exports, $__module) {
  var _retrieveGlobal = $__System.get("@@global-helpers").prepareGlobal($__module.id, null, null);
  (function() {})();
  return _retrieveGlobal();
});

$__System.registerDynamic("5", [], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  function normalizeArray(parts, allowAboveRoot) {
    var up = 0;
    for (var i = parts.length - 1; i >= 0; i--) {
      var last = parts[i];
      if (last === '.') {
        parts.splice(i, 1);
      } else if (last === '..') {
        parts.splice(i, 1);
        up++;
      } else if (up) {
        parts.splice(i, 1);
        up--;
      }
    }
    if (allowAboveRoot) {
      for (; up--; up) {
        parts.unshift('..');
      }
    }
    return parts;
  }
  var splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;
  var splitPath = function(filename) {
    return splitPathRe.exec(filename).slice(1);
  };
  exports.resolve = function() {
    var resolvedPath = '',
        resolvedAbsolute = false;
    for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
      var path = (i >= 0) ? arguments[i] : process.cwd();
      if (typeof path !== 'string') {
        throw new TypeError('Arguments to path.resolve must be strings');
      } else if (!path) {
        continue;
      }
      resolvedPath = path + '/' + resolvedPath;
      resolvedAbsolute = path.charAt(0) === '/';
    }
    resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {
      return !!p;
    }), !resolvedAbsolute).join('/');
    return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
  };
  exports.normalize = function(path) {
    var isAbsolute = exports.isAbsolute(path),
        trailingSlash = substr(path, -1) === '/';
    path = normalizeArray(filter(path.split('/'), function(p) {
      return !!p;
    }), !isAbsolute).join('/');
    if (!path && !isAbsolute) {
      path = '.';
    }
    if (path && trailingSlash) {
      path += '/';
    }
    return (isAbsolute ? '/' : '') + path;
  };
  exports.isAbsolute = function(path) {
    return path.charAt(0) === '/';
  };
  exports.join = function() {
    var paths = Array.prototype.slice.call(arguments, 0);
    return exports.normalize(filter(paths, function(p, index) {
      if (typeof p !== 'string') {
        throw new TypeError('Arguments to path.join must be strings');
      }
      return p;
    }).join('/'));
  };
  exports.relative = function(from, to) {
    from = exports.resolve(from).substr(1);
    to = exports.resolve(to).substr(1);
    function trim(arr) {
      var start = 0;
      for (; start < arr.length; start++) {
        if (arr[start] !== '')
          break;
      }
      var end = arr.length - 1;
      for (; end >= 0; end--) {
        if (arr[end] !== '')
          break;
      }
      if (start > end)
        return [];
      return arr.slice(start, end - start + 1);
    }
    var fromParts = trim(from.split('/'));
    var toParts = trim(to.split('/'));
    var length = Math.min(fromParts.length, toParts.length);
    var samePartsLength = length;
    for (var i = 0; i < length; i++) {
      if (fromParts[i] !== toParts[i]) {
        samePartsLength = i;
        break;
      }
    }
    var outputParts = [];
    for (var i = samePartsLength; i < fromParts.length; i++) {
      outputParts.push('..');
    }
    outputParts = outputParts.concat(toParts.slice(samePartsLength));
    return outputParts.join('/');
  };
  exports.sep = '/';
  exports.delimiter = ':';
  exports.dirname = function(path) {
    var result = splitPath(path),
        root = result[0],
        dir = result[1];
    if (!root && !dir) {
      return '.';
    }
    if (dir) {
      dir = dir.substr(0, dir.length - 1);
    }
    return root + dir;
  };
  exports.basename = function(path, ext) {
    var f = splitPath(path)[2];
    if (ext && f.substr(-1 * ext.length) === ext) {
      f = f.substr(0, f.length - ext.length);
    }
    return f;
  };
  exports.extname = function(path) {
    return splitPath(path)[3];
  };
  function filter(xs, f) {
    if (xs.filter)
      return xs.filter(f);
    var res = [];
    for (var i = 0; i < xs.length; i++) {
      if (f(xs[i], i, xs))
        res.push(xs[i]);
    }
    return res;
  }
  var substr = 'ab'.substr(-1) === 'b' ? function(str, start, len) {
    return str.substr(start, len);
  } : function(str, start, len) {
    if (start < 0)
      start = str.length + start;
    return str.substr(start, len);
  };
  ;
  return module.exports;
});

$__System.registerDynamic("15", [], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  function EventEmitter() {
    this._events = this._events || {};
    this._maxListeners = this._maxListeners || undefined;
  }
  module.exports = EventEmitter;
  EventEmitter.EventEmitter = EventEmitter;
  EventEmitter.prototype._events = undefined;
  EventEmitter.prototype._maxListeners = undefined;
  EventEmitter.defaultMaxListeners = 10;
  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 (type === 'error') {
      if (!this._events.error || (isObject(this._events.error) && !this._events.error.length)) {
        er = arguments[1];
        if (er instanceof Error) {
          throw er;
        }
        throw TypeError('Uncaught, unspecified "error" event.');
      }
    }
    handler = this._events[type];
    if (isUndefined(handler))
      return false;
    if (isFunction(handler)) {
      switch (arguments.length) {
        case 1:
          handler.call(this);
          break;
        case 2:
          handler.call(this, arguments[1]);
          break;
        case 3:
          handler.call(this, arguments[1], arguments[2]);
          break;
        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 = {};
    if (this._events.newListener)
      this.emit('newListener', type, isFunction(listener.listener) ? listener.listener : listener);
    if (!this._events[type])
      this._events[type] = listener;
    else if (isObject(this._events[type]))
      this._events[type].push(listener);
    else
      this._events[type] = [this._events[type], listener];
    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') {
          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;
  };
  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;
    if (!this._events.removeListener) {
      if (arguments.length === 0)
        this._events = {};
      else if (this._events[type])
        delete this._events[type];
      return this;
    }
    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 {
      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;
  }
  return module.exports;
});

$__System.registerDynamic("16", ["4", "5", "15"], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  module.exports = function(LiveScript) {
    var fs,
        path,
        events;
    fs = $__require('4');
    path = $__require('5');
    events = $__require('15');
    LiveScript.run = function(code, options, arg$) {
      var filename,
          ref$,
          js,
          context,
          main,
          dirname,
          e;
      if (options != null) {
        filename = options.filename;
      }
      ref$ = arg$ != null ? arg$ : {}, js = ref$.js, context = ref$.context;
      main = $__require.main;
      if (filename) {
        dirname = path.dirname(fs.realpathSync(filename = process.argv[1] = path.resolve(filename)));
      } else {
        dirname = filename = '.';
      }
      main.paths = main.constructor._nodeModulePaths(dirname);
      main.filename = filename;
      if (!js) {
        code = LiveScript.compile(code, (ref$ = {}, import$(ref$, options), ref$.bare = true, ref$));
      }
      if (context) {
        global.__runContext = context;
        code = "return (function() {\n" + code + "\n}).call(global.__runContext);";
      }
      try {
        return main._compile(code, filename);
      } catch (e$) {
        e = e$;
        throw hackTrace(e, code, filename);
      }
    };
    importAll$(LiveScript, events.EventEmitter.prototype);
    $__require.extensions['.ls'] = function(module, filename) {
      var file,
          js,
          e;
      file = fs.readFileSync(filename, 'utf8');
      js = '.json.ls' === filename.substr(-8) ? 'module.exports = ' + LiveScript.compile(file, {
        filename: filename,
        json: true
      }) : LiveScript.compile(file, {
        filename: filename,
        bare: true,
        map: "embedded"
      }).code;
      try {
        return module._compile(js, filename);
      } catch (e$) {
        e = e$;
        throw hackTrace(e, js, filename);
      }
    };
  };
  function hackTrace(error, js, filename) {
    var stack,
        traces,
        i$,
        len$,
        i,
        trace,
        index,
        lno,
        end,
        length,
        lines,
        j$,
        ref$,
        n;
    if (error != null) {
      stack = error.stack;
    }
    if (!stack) {
      return error;
    }
    traces = stack.split('\n');
    if (!(traces.length > 1)) {
      return error;
    }
    for (i$ = 0, len$ = traces.length; i$ < len$; ++i$) {
      i = i$;
      trace = traces[i$];
      if (0 > (index = trace.indexOf("(" + filename + ":"))) {
        continue;
      }
      lno = (/:(\d+):/.exec(trace.slice(index + filename.length)) || '')[1];
      if (!(lno = +lno)) {
        continue;
      }
      end = lno + 4;
      length = ('' + end).length;
      lines || (lines = js.split('\n'));
      for (j$ = 1 > (ref$ = lno - 4) ? 1 : ref$; j$ <= end; ++j$) {
        n = j$;
        traces[i] += "\n" + ('    ' + n).slice(-length) + "" + '|+'.charAt(n === lno) + " " + [lines[n - 1]];
      }
    }
    return error.stack = traces.join('\n'), error;
  }
  function import$(obj, src) {
    var own = {}.hasOwnProperty;
    for (var key in src)
      if (own.call(src, key))
        obj[key] = src[key];
    return obj;
  }
  function importAll$(obj, src) {
    for (var key in src)
      obj[key] = src[key];
    return obj;
  }
  return module.exports;
});

$__System.registerDynamic("17", ["2", "3", "7", "9", "5", "16"], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  var lexer,
      parser,
      ast,
      SourceNode,
      path,
      toString$ = {}.toString;
  lexer = $__require('2');
  parser = $__require('3').parser;
  ast = $__require('7');
  SourceNode = $__require('9').SourceNode;
  path = $__require('5');
  parser.yy = ast;
  parser.lexer = {
    lex: function() {
      var ref$,
          tag,
          first_line,
          first_column,
          last_line,
          last_column;
      ref$ = this.tokens[++this.pos] || [''], tag = ref$[0], this.yytext = ref$[1], first_line = ref$[2], first_column = ref$[3];
      ref$ = this.tokens[this.pos + 1] || [''], last_line = ref$[2], last_column = ref$[3];
      this.yylineno = first_line;
      this.yylloc = {
        first_line: first_line,
        first_column: first_column,
        last_line: last_line,
        last_column: last_column
      };
      return tag;
    },
    setInput: function(it) {
      this.pos = -1;
      return this.tokens = it;
    },
    upcomingInput: function() {
      return '';
    }
  };
  exports.VERSION = '1.5.0';
  exports.compile = function(code, options) {
    var result,
        ast,
        output,
        filename,
        outputFilename,
        ref$,
        mapPath,
        e,
        that;
    options == null && (options = {});
    options.header == null && (options.header = true);
    try {
      if (options.json) {
        result = Function(exports.compile(code, {
          bare: true,
          run: true,
          print: true
        }))();
        return JSON.stringify(result, null, 2) + "\n";
      } else {
        ast = parser.parse(lexer.lex(code));
        if (options.run && options.print) {
          ast.makeReturn();
        }
        output = ast.compileRoot(options);
        if (options.header) {
          output = new SourceNode(null, null, null, ["// Generated by LiveScript " + exports.VERSION + "\n", output]);
        }
        if (options.map && options.map !== 'none') {
          filename = options.filename, outputFilename = options.outputFilename;
          if (!filename) {
            filename = "unnamed-" + Math.floor(Math.random() * 4294967296).toString(16) + ".ls";
          }
          output.setFile(filename);
          result = output.toStringWithSourceMap();
          if (options.map === 'embedded') {
            result.map.setSourceContent(filename, code);
          }
          if ((ref$ = options.map) === 'linked' || ref$ === 'debug') {
            mapPath = outputFilename + ".map";
            result.code += "\n//# sourceMappingURL=" + mapPath + "\n";
          } else {
            result.code += "\n" + new Buffer(result.map.toString()).toString('base64') + "\n";
          }
          return result;
        } else {
          return output.toString();
        }
      }
    } catch (e$) {
      e = e$;
      if (that = options.filename) {
        e.message += "\nat " + that;
      }
      throw e;
    }
  };
  exports.ast = function(it) {
    return parser.parse(typeof it === 'string' ? lexer.lex(it) : it);
  };
  exports.tokens = lexer.lex;
  exports.lex = function(it) {
    return lexer.lex(it, {raw: true});
  };
  exports.run = function(code, options) {
    var output,
        ref$;
    output = exports.compile(code, (ref$ = {}, import$(ref$, options), ref$.bare = true, ref$));
    return Function(toString$.call(output).slice(8, -1) === 'String' ? output : output.code)();
  };
  exports.tokens.rewrite = lexer.rewrite;
  importAll$(exports.ast, parser.yy);
  if ($__require.extensions) {
    $__require('16')(exports);
  } else {
    exports.require = $__require;
  }
  function import$(obj, src) {
    var own = {}.hasOwnProperty;
    for (var key in src)
      if (own.call(src, key))
        obj[key] = src[key];
    return obj;
  }
  function importAll$(obj, src) {
    for (var key in src)
      obj[key] = src[key];
    return obj;
  }
  return module.exports;
});

$__System.registerDynamic("18", ["19", "1a", "17"], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  var $,
      seqr,
      livescript,
      localizer;
  $ = $__require('19');
  seqr = $__require('1a');
  livescript = $__require('17');
  module.exports = localizer = function() {
    var self;
    self = function(msg) {
      var args,
          res$,
          i$,
          to$,
          handler,
          ref$;
      res$ = [];
      for (i$ = 1, to$ = arguments.length; i$ < to$; ++i$) {
        res$.push(arguments[i$]);
      }
      args = res$;
      handler = (ref$ = self.mapping[msg]) != null ? ref$ : msg;
      if (handler.apply == null) {
        return handler;
      }
      return handler.apply(self, args);
    };
    self.mapping = {};
    self.load = seqr.bind(function*(file) {
      var data;
      data = (yield $.ajax(file, {dataType: "text"}));
      return import$(self.mapping, eval(livescript.compile(data, {
        bare: true,
        header: false,
        filename: file
      })));
    });
    return self;
  };
  function import$(obj, src) {
    var own = {}.hasOwnProperty;
    for (var key in src)
      if (own.call(src, key))
        obj[key] = src[key];
    return obj;
  }
  return module.exports;
});

$__System.registerDynamic("1b", [], false, function($__require, $__exports, $__module) {
  var _retrieveGlobal = $__System.get("@@global-helpers").prepareGlobal($__module.id, null, null);
  (function() {
    THREE.CannonDebugRenderer = function(scene, world, options) {
      options = options || {};
      this.scene = scene;
      this.world = world;
      this._meshes = [];
      this._material = new THREE.MeshBasicMaterial({
        color: 0x00ff00,
        wireframe: true
      });
      this._sphereGeometry = new THREE.SphereGeometry(1);
      this._boxGeometry = new THREE.BoxGeometry(1, 1, 1);
      this._planeGeometry = new THREE.PlaneGeometry(10, 10, 10, 10);
      this._cylinderGeometry = new THREE.CylinderGeometry(1, 1, 10, 10);
    };
    THREE.CannonDebugRenderer.prototype = {
      tmpVec0: new CANNON.Vec3(),
      tmpVec1: new CANNON.Vec3(),
      tmpVec2: new CANNON.Vec3(),
      tmpQuat0: new CANNON.Vec3(),
      update: function() {
        var bodies = this.world.bodies;
        var meshes = this._meshes;
        var shapeWorldPosition = this.tmpVec0;
        var shapeWorldQuaternion = this.tmpQuat0;
        var meshIndex = 0;
        for (var i = 0; i !== bodies.length; i++) {
          var body = bodies[i];
          for (var j = 0; j !== body.shapes.length; j++) {
            var shape = body.shapes[j];
            this._updateMesh(meshIndex, body, shape);
            var mesh = meshes[meshIndex];
            if (mesh) {
              body.quaternion.vmult(body.shapeOffsets[j], shapeWorldPosition);
              body.position.vadd(shapeWorldPosition, shapeWorldPosition);
              body.quaternion.mult(body.shapeOrientations[j], shapeWorldQuaternion);
              mesh.position.copy(shapeWorldPosition);
              mesh.quaternion.copy(shapeWorldQuaternion);
            }
            meshIndex++;
          }
        }
        for (var i = meshIndex; i < meshes.length; i++) {
          var mesh = meshes[i];
          if (mesh) {
            this.scene.remove(mesh);
          }
        }
        meshes.length = meshIndex;
      },
      _updateMesh: function(index, body, shape) {
        var mesh = this._meshes[index];
        if (!this._typeMatch(mesh, shape)) {
          if (mesh) {
            this.scene.remove(mesh);
          }
          mesh = this._meshes[index] = this._createMesh(shape);
        }
        this._scaleMesh(mesh, shape);
      },
      _typeMatch: function(mesh, shape) {
        if (!mesh) {
          return false;
        }
        var geo = mesh.geometry;
        return ((geo instanceof THREE.SphereGeometry && shape instanceof CANNON.Sphere) || (geo instanceof THREE.BoxGeometry && shape instanceof CANNON.Box) || (geo instanceof THREE.PlaneGeometry && shape instanceof CANNON.Plane) || (geo.id === shape.geometryId && shape instanceof CANNON.ConvexPolyhedron) || (geo.id === shape.geometryId && shape instanceof CANNON.Trimesh) || (geo.id === shape.geometryId && shape instanceof CANNON.Heightfield));
      },
      _createMesh: function(shape) {
        var mesh;
        var material = this._material;
        switch (shape.type) {
          case CANNON.Shape.types.SPHERE:
            mesh = new THREE.Mesh(this._sphereGeometry, material);
            break;
          case CANNON.Shape.types.BOX:
            mesh = new THREE.Mesh(this._boxGeometry, material);
            break;
          case CANNON.Shape.types.PLANE:
            mesh = new THREE.Mesh(this._planeGeometry, material);
            break;
          case CANNON.Shape.types.CONVEXPOLYHEDRON:
            var geo = new THREE.Geometry();
            for (var i = 0; i < shape.vertices.length; i++) {
              var v = shape.vertices[i];
              geo.vertices.push(new THREE.Vector3(v.x, v.y, v.z));
            }
            for (var i = 0; i < shape.faces.length; i++) {
              var face = shape.faces[i];
              var a = face[0];
              for (var j = 1; j < face.length - 1; j++) {
                var b = face[j];
                var c = face[j + 1];
                geo.faces.push(new THREE.Face3(a, b, c));
              }
            }
            geo.computeBoundingSphere();
            geo.computeFaceNormals();
            mesh = new THREE.Mesh(geo, material);
            shape.geometryId = geo.id;
            break;
          case CANNON.Shape.types.TRIMESH:
            var geometry = new THREE.Geometry();
            var v0 = this.tmpVec0;
            var v1 = this.tmpVec1;
            var v2 = this.tmpVec2;
            for (var i = 0; i < shape.indices.length / 3; i++) {
              shape.getTriangleVertices(i, v0, v1, v2);
              geometry.vertices.push(new THREE.Vector3(v0.x, v0.y, v0.z), new THREE.Vector3(v1.x, v1.y, v1.z), new THREE.Vector3(v2.x, v2.y, v2.z));
              var j = geometry.vertices.length - 3;
              geometry.faces.push(new THREE.Face3(j, j + 1, j + 2));
            }
            geometry.computeBoundingSphere();
            geometry.computeFaceNormals();
            mesh = new THREE.Mesh(geometry, material);
            shape.geometryId = geometry.id;
            break;
          case CANNON.Shape.types.HEIGHTFIELD:
            var geometry = new THREE.Geometry();
            var v0 = this.tmpVec0;
            var v1 = this.tmpVec1;
            var v2 = this.tmpVec2;
            for (var xi = 0; xi < shape.data.length - 1; xi++) {
              for (var yi = 0; yi < shape.data[xi].length - 1; yi++) {
                for (var k = 0; k < 2; k++) {
                  shape.getConvexTrianglePillar(xi, yi, k === 0);
                  v0.copy(shape.pillarConvex.vertices[0]);
                  v1.copy(shape.pillarConvex.vertices[1]);
                  v2.copy(shape.pillarConvex.vertices[2]);
                  v0.vadd(shape.pillarOffset, v0);
                  v1.vadd(shape.pillarOffset, v1);
                  v2.vadd(shape.pillarOffset, v2);
                  geometry.vertices.push(new THREE.Vector3(v0.x, v0.y, v0.z), new THREE.Vector3(v1.x, v1.y, v1.z), new THREE.Vector3(v2.x, v2.y, v2.z));
                  var i = geometry.vertices.length - 3;
                  geometry.faces.push(new THREE.Face3(i, i + 1, i + 2));
                }
              }
            }
            geometry.computeBoundingSphere();
            geometry.computeFaceNormals();
            mesh = new THREE.Mesh(geometry, material);
            shape.geometryId = geometry.id;
            break;
        }
        if (mesh) {
          this.scene.add(mesh);
        }
        return mesh;
      },
      _scaleMesh: function(mesh, shape) {
        switch (shape.type) {
          case CANNON.Shape.types.SPHERE:
            var radius = shape.radius;
            mesh.scale.set(radius, radius, radius);
            break;
          case CANNON.Shape.types.BOX:
            mesh.scale.copy(shape.halfExtents);
            mesh.scale.multiplyScalar(2);
            break;
          case CANNON.Shape.types.CONVEXPOLYHEDRON:
            mesh.scale.set(1, 1, 1);
            break;
          case CANNON.Shape.types.TRIMESH:
            mesh.scale.copy(shape.scale);
            break;
          case CANNON.Shape.types.HEIGHTFIELD:
            mesh.scale.set(1, 1, 1);
            break;
        }
      }
    };
  })();
  return _retrieveGlobal();
});

(function() {
var define = $__System.amdDefine;
"use strict";
function _instanceof(a, b) {
  return null != b && b[Symbol.hasInstance] ? b[Symbol.hasInstance](a) : a instanceof b;
}
!function(a) {
  var b = a.IDBKeyRange || a.webkitIDBKeyRange,
      c = {
        readonly: "readonly",
        readwrite: "readwrite"
      },
      d = Object.prototype.hasOwnProperty,
      e = function(a) {
        return a;
      },
      f = function() {
        if (!f && (f = a.indexedDB || a.webkitIndexedDB || a.mozIndexedDB || a.oIndexedDB || a.msIndexedDB || (null === a.indexedDB && a.shimIndexedDB ? a.shimIndexedDB : void 0), !f))
          throw new Error("IndexedDB required");
        return f;
      }(),
      g = {},
      h = function(a, b) {
        var d = this,
            e = !1;
        this.getIndexedDB = function() {
          return a;
        }, this.add = function(b) {
          if (e)
            throw new Error("Database has been closed");
          for (var d = [],
              f = Array.isArray,
              g = arguments.length,
              h = Array(g > 1 ? g - 1 : 0),
              i = 1; g > i; i++)
            h[i - 1] = arguments[i];
          for (var j = 0,
              k = h.length; k > j; j++) {
            var l = h[j];
            f(l) ? d = d.concat(l) : d.push(l);
          }
          var m = a.transaction(b, c.readwrite),
              n = m.objectStore(b);
          return new Promise(function(a, b) {
            var c = this;
            d.forEach(function(a) {
              var b;
              if (a.item && a.key) {
                var c = a.key;
                a = a.item, b = n.add(a, c);
              } else
                b = n.add(a);
              b.onsuccess = function(b) {
                var c = b.target,
                    d = c.source.keyPath;
                null === d && (d = "__id__"), Object.defineProperty(a, d, {
                  value: c.result,
                  enumerable: !0
                });
              };
            }), m.oncomplete = function() {
              return a(d, c);
            }, m.onerror = function(a) {
              a.preventDefault(), b(a);
            }, m.onabort = function(a) {
              return b(a);
            };
          });
        }, this.update = function(b) {
          for (var d = arguments.length,
              f = Array(d > 1 ? d - 1 : 0),
              g = 1; d > g; g++)
            f[g - 1] = arguments[g];
          if (e)
            throw new Error("Database has been closed");
          var h = a.transaction(b, c.readwrite),
              i = h.objectStore(b);
          return new Promise(function(a, b) {
            var c = this;
            f.forEach(function(a) {
              if (a.item && a.key) {
                var b = a.key;
                a = a.item, i.put(a, b);
              } else
                i.put(a);
            }), h.oncomplete = function() {
              return a(f, c);
            }, h.onerror = function(a) {
              return b(a);
            }, h.onabort = function(a) {
              return b(a);
            };
          });
        }, this.remove = function(b, d) {
          if (e)
            throw new Error("Database has been closed");
          var f = a.transaction(b, c.readwrite),
              g = f.objectStore(b);
          return new Promise(function(a, b) {
            g["delete"](d), f.oncomplete = function() {
              return a(d);
            }, f.onerror = function(a) {
              return b(a);
            };
          });
        }, this.clear = function(b) {
          if (e)
            throw new Error("Database has been closed");
          var d = a.transaction(b, c.readwrite),
              f = d.objectStore(b);
          return f.clear(), new Promise(function(a, b) {
            d.oncomplete = function() {
              return a();
            }, d.onerror = function(a) {
              return b(a);
            };
          });
        }, this.close = function() {
          if (e)
            throw new Error("Database has been closed");
          a.close(), e = !0, delete g[b];
        }, this.get = function(b, c) {
          if (e)
            throw new Error("Database has been closed");
          var d = a.transaction(b),
              f = d.objectStore(b),
              g = f.get(c);
          return new Promise(function(a, b) {
            g.onsuccess = function(b) {
              return a(b.target.result);
            }, d.onerror = function(a) {
              return b(a);
            };
          });
        }, this.query = function(b, c) {
          if (e)
            throw new Error("Database has been closed");
          return new i(b, a, c);
        }, this.count = function(b, c) {
          if (e)
            throw new Error("Database has been closed");
          var d = a.transaction(b),
              f = d.objectStore(b);
          return new Promise(function(a, b) {
            var c = f.count();
            c.onsuccess = function(b) {
              return a(b.target.result);
            }, d.onerror = function(a) {
              return b(a);
            };
          });
        }, [].map.call(a.objectStoreNames, function(a) {
          d[a] = {};
          var b = Object.keys(d);
          b.filter(function(a) {
            return "close" !== a;
          }).map(function(b) {
            return d[a][b] = function() {
              for (var c = arguments.length,
                  e = Array(c),
                  f = 0; c > f; f++)
                e[f] = arguments[f];
              return d[b].apply(d, [a].concat(e));
            };
          });
        });
      },
      i = function(a, d, f) {
        var g = this,
            h = !1,
            i = function(e, g, i, j, k, l, m) {
              var n = d.transaction(a, h ? c.readwrite : c.readonly),
                  o = n.objectStore(a),
                  p = f ? o.index(f) : o,
                  q = e ? b[e].apply(null, g) : null,
                  r = [],
                  s = [q],
                  t = 0;
              k = k || null, l = l || [], "count" !== i && s.push(j || "next");
              var u = h ? Object.keys(h) : !1,
                  v = function(a) {
                    for (var b = 0; b < u.length; b++) {
                      var c = u[b],
                          d = h[c];
                      _instanceof(d, Function) && (d = d(a)), a[c] = d;
                    }
                    return a;
                  };
              return p[i].apply(p, s).onsuccess = function(a) {
                var b = a.target.result;
                if ("number" == typeof b)
                  r = b;
                else if (b)
                  if (null !== k && k[0] > t)
                    t = k[0], b.advance(k[0]);
                  else if (null !== k && t >= k[0] + k[1])
                    ;
                  else {
                    var c = !0,
                        d = "value" in b ? b.value : b.key;
                    l.forEach(function(a) {
                      a && a.length && (c = 2 === a.length ? c && d[a[0]] === a[1] : c && a[0].apply(void 0, [d]));
                    }), c && (t++, r.push(m(d)), h && (d = v(d), b.update(d))), b["continue"]();
                  }
              }, new Promise(function(a, b) {
                n.oncomplete = function() {
                  return a(r);
                }, n.onerror = function(a) {
                  return b(a);
                }, n.onabort = function(a) {
                  return b(a);
                };
              });
            },
            j = function(a, b) {
              var c,
                  d,
                  f,
                  g,
                  j,
                  k = "next",
                  l = "openCursor",
                  m = [],
                  n = null,
                  o = e,
                  p = !1,
                  q = function() {
                    return i(a, b, l, p ? k + "unique" : k, n, m, o);
                  },
                  r = function() {
                    return n = Array.prototype.slice.call(arguments, 0, 2), 1 === n.length && n.unshift(0), {execute: q};
                  },
                  s = function() {
                    return k = null, l = "count", {execute: q};
                  },
                  t = function() {
                    return l = "openKeyCursor", {
                      desc: d,
                      execute: q,
                      filter: c,
                      distinct: f,
                      map: j
                    };
                  };
              return c = function() {
                return m.push(Array.prototype.slice.call(arguments, 0, 2)), {
                  keys: t,
                  execute: q,
                  filter: c,
                  desc: d,
                  distinct: f,
                  modify: g,
                  limit: r,
                  map: j
                };
              }, d = function() {
                return k = "prev", {
                  keys: t,
                  execute: q,
                  filter: c,
                  distinct: f,
                  modify: g,
                  map: j
                };
              }, f = function() {
                return p = !0, {
                  keys: t,
                  count: s,
                  execute: q,
                  filter: c,
                  desc: d,
                  modify: g,
                  map: j
                };
              }, g = function(a) {
                return h = a, {execute: q};
              }, j = function(a) {
                return o = a, {
                  execute: q,
                  count: s,
                  keys: t,
                  filter: c,
                  desc: d,
                  distinct: f,
                  modify: g,
                  limit: r,
                  map: j
                };
              }, {
                execute: q,
                count: s,
                keys: t,
                filter: c,
                desc: d,
                distinct: f,
                modify: g,
                limit: r,
                map: j
              };
            };
        ["only", "bound", "upperBound", "lowerBound"].forEach(function(a) {
          g[a] = function() {
            return j(a, arguments);
          };
        }), this.filter = function() {
          var a = j(null, null);
          return a.filter.apply(a, arguments);
        }, this.all = function() {
          return this.filter();
        };
      },
      j = function(a, b, c) {
        "function" == typeof b && (b = b());
        var e;
        for (e in b) {
          var f,
              g = b[e];
          f = !d.call(b, e) || c.objectStoreNames.contains(e) ? a.currentTarget.transaction.objectStore(e) : c.createObjectStore(e, g.key);
          var h;
          for (h in g.indexes) {
            var i = g.indexes[h];
            try {
              f.index(h);
            } catch (j) {
              f.createIndex(h, i.key || h, Object.keys(i).length ? i : {unique: !1});
            }
          }
        }
      },
      k = function(a, b, c, d) {
        var e = a.target.result,
            f = new h(e, b);
        return g[b] = e, Promise.resolve(f);
      },
      l = {
        version: "0.11.0",
        open: function(a) {
          return new Promise(function(b, c) {
            if (g[a.server])
              k({target: {result: g[a.server]}}, a.server, a.version, a.schema).then(b, c);
            else {
              var d = f.open(a.server, a.version);
              d.onsuccess = function(d) {
                return k(d, a.server, a.version, a.schema).then(b, c);
              }, d.onupgradeneeded = function(b) {
                return j(b, a.schema, b.target.result);
              }, d.onerror = function(a) {
                return c(a);
              };
            }
          });
        },
        "delete": function(a) {
          return new Promise(function(b, c) {
            var d = f.deleteDatabase(a);
            d.onsuccess = function() {
              return b();
            }, d.onerror = function(a) {
              return c(a);
            }, d.onblocked = function(a) {
              return c(a);
            };
          });
        }
      };
  "undefined" != typeof module && "undefined" != typeof module.exports ? module.exports = l : "function" == typeof define && define.amd ? define("1c", [], function() {
    return l;
  }) : a.db = l;
}(window);

})();
$__System.registerDynamic("1d", ["1c"], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  var dbjs,
      Sessions,
      _Sessions,
      Session,
      out$ = typeof exports != 'undefined' && exports || this;
  dbjs = $__require('1c');
  out$.Sessions = Sessions = function(name) {
    return dbjs.open({
      server: name,
      version: 2,
      schema: {
        sessions: {key: {
            keyPath: 'sessionSurrogateId',
            autoIncrement: true
          }},
        entries: {
          key: {autoIncrement: true},
          indexes: {sessionId: {}}
        }
      }
    }).then(function(db) {
      return new _Sessions(db);
    });
  };
  _Sessions = (function() {
    _Sessions.displayName = '_Sessions';
    var prototype = _Sessions.prototype,
        constructor = _Sessions;
    function _Sessions(db) {
      this.db = db;
    }
    _Sessions.prototype.create = function(info) {
      var this$ = this;
      return this.db.sessions.add(info).then(function(arg$) {
        var entry;
        entry = arg$[0];
        return new Session(this$.db, entry.sessionSurrogateId);
      });
    };
    return _Sessions;
  }());
  Session = (function() {
    Session.displayName = 'Session';
    var prototype = Session.prototype,
        constructor = Session;
    function Session(db, sessionId) {
      this.db = db;
      this.sessionId = sessionId;
      this._flush = bind$(this, '_flush', prototype);
      this.write = bind$(this, 'write', prototype);
      this._queue = [];
      this._pending = void 8;
    }
    Session.prototype.write = function(data) {
      this._queue.push({
        sessionId: this.sessionId,
        time: Date.now() / 1000,
        data: data
      });
      return this._flush();
    };
    Session.prototype._flush = function() {
      var buffer,
          buflen,
          startTime,
          ref$,
          reschedule,
          this$ = this;
      if (this._pending) {
        return;
      }
      if (this._queue.length === 0) {
        return;
      }
      buffer = this._queue;
      this._queue = [];
      buflen = buffer.length;
      startTime = Date.now();
      this._pending = (ref$ = this.db.entries).add.apply(ref$, buffer);
      reschedule = function() {
        var duration;
        duration = (Date.now() - startTime) / 1000;
        this$._pending = void 8;
        return setTimeout(this$._flush, 0);
      };
      return this._pending.then(reschedule, reschedule);
    };
    return Session;
  }());
  function bind$(obj, key, target) {
    return function() {
      return (target || obj)[key].apply(obj, arguments);
    };
  }
  return module.exports;
});

$__System.registerDynamic("1e", ["19", "1f", "20", "1a", "21", "22", "23", "24", "18", "25", "26", "1b", "1d"], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  var $,
      deparam,
      P,
      Promise,
      Co,
      seqr,
      Signal,
      ref$,
      KeyboardController,
      WsController,
      scenario,
      ui,
      localizer,
      THREE,
      eachFrame,
      audioContext,
      Sessions,
      _logger,
      getLogger,
      _wsLogger,
      wsLogger,
      dumpPhysics,
      newEnv,
      runScenario,
      out$ = typeof exports != 'undefined' && exports || this,
      slice$ = [].slice;
  $ = $__require('19');
  deparam = $__require('1f');
  P = Promise = $__require('20');
  Promise.config({longStackTraces: true});
  Co = P.coroutine;
  seqr = $__require('1a');
  Signal = $__require('21').Signal;
  ref$ = $__require('22'), KeyboardController = ref$.KeyboardController, WsController = ref$.WsController;
  scenario = $__require('23');
  ui = $__require('24');
  localizer = $__require('18');
  window.THREE = THREE = $__require('25');
  window.CANNON = $__require('26');
  $__require('1b');
  eachFrame = function(f) {
    return new P(function(accept, reject) {
      var stopped,
          clock,
          tick;
      stopped = false;
      clock = new THREE.Clock;
      tick = function() {
        var dt,
            result;
        if (stopped) {
          return;
        }
        requestAnimationFrame(tick);
        dt = clock.getDelta();
        result = f(dt);
        if (result != null) {
          accept(result);
          return stopped = true;
        }
      };
      return tick();
    });
  };
  audioContext = new AudioContext;
  Sessions = $__require('1d').Sessions;
  _logger = void 8;
  getLogger = seqr.bind(function*() {
    var startTime,
        p,
        sessions;
    if (_logger != null) {
      return _logger;
    }
    startTime = (new Date).toISOString();
    p = Sessions("wtsSessions");
    console.log(p);
    sessions = (yield p);
    _logger = (yield sessions.create({date: startTime}));
    return _logger;
  });
  _wsLogger = void 8;
  wsLogger = seqr.bind(function*(url, orig) {
    var socket,
        ref$;
    orig == null && (orig = {});
    if (_wsLogger != null) {
      return _wsLogger;
    }
    socket = (yield new Promise(function(accept, reject) {
      var socket;
      socket = new WebSocket(url);
      socket.onopen = function() {
        return accept(socket);
      };
      return socket.onerror = function(ev) {
        console.error("Failed to open logging socket", ev);
        return reject("Failed to open logging socket " + url + ".");
      };
    }));
    _wsLogger = (ref$ = clone$(orig), ref$.write = function(data) {
      orig.write(data);
      return socket.send(JSON.stringify({
        time: Date.now() / 1000,
        data: data
      }));
    }, ref$.close = function() {}, ref$);
    return _wsLogger;
  });
  dumpPhysics = function(world) {
    var ret,
        res$,
        i$,
        ref$,
        len$,
        body,
        ref1$;
    ret = {time: world.time};
    res$ = [];
    for (i$ = 0, len$ = (ref$ = world.bodies).length; i$ < len$; ++i$) {
      body = ref$[i$];
      res$.push({
        id: body.id,
        index: body.index,
        position: {
          x: (ref1$ = body.position).x,
          y: ref1$.y,
          z: ref1$.z
        },
        quaternion: {
          x: (ref1$ = body.quaternion).x,
          y: ref1$.y,
          z: ref1$.z,
          w: ref1$.w
        },
        velocity: {
          x: (ref1$ = body.velocity).x,
          y: ref1$.y,
          z: ref1$.z
        },
        angularVelocity: {
          x: (ref1$ = body.angularVelocity).x,
          y: ref1$.y,
          z: ref1$.z
        },
        objectClass: body.objectClass,
        objectName: body.objectName
      });
    }
    ret.bodies = res$;
    return ret;
  };
  out$.newEnv = newEnv = seqr.bind(function*() {
    var env,
        opts,
        lang,
        ref$,
        container,
        onSize,
        dispatchResize,
        controls,
        id;
    env = {};
    opts = {};
    import$(opts, deparam(window.location.search.substring(1)));
    env.L = localizer();
    lang = (ref$ = opts.lang) != null ? ref$ : 'en';
    (yield env.L.load("locales/" + lang + ".lson"));
    container = $('#drivesim').empty().fadeIn();
    onSize = Signal({onAdd: function(cb) {
        return cb(container.width(), container.height());
      }});
    dispatchResize = function() {
      return onSize.dispatch(container.width(), container.height());
    };
    $(window).on("resize", dispatchResize);
    this['finally'](function() {
      $(window).off("resize", dispatchResize);
    });
    env.container = container;
    env.audioContext = audioContext;
    env.onSize = onSize;
    env.opts = opts;
    if (!opts.disableDefaultLogger) {
      env.logger = (yield getLogger());
    } else {
      env.logger = {
        write: function() {},
        close: function() {}
      };
    }
    if (opts.wsLogger != null) {
      env.logger = (yield wsLogger(opts.wsLogger, env.logger));
    }
    this['finally'](function() {
      return env.logger.close();
    });
    if (opts.controller != null) {
      env.controls = controls = (yield WsController.Connect(opts.controller));
    } else {
      env.controls = new KeyboardController;
    }
    this['finally'](function() {
      return env.controls.close();
    });
    env.controls.change(function() {
      var args,
          res$,
          i$,
          to$;
      res$ = [];
      for (i$ = 0, to$ = arguments.length; i$ < to$; ++i$) {
        res$.push(arguments[i$]);
      }
      args = res$;
      return env.logger.write({controlsChange: args});
    });
    env.uiUpdate = Signal();
    id = setInterval(env.uiUpdate.dispatch, 1 / 60 * 1000);
    this['finally'](function() {
      clearInterval(id);
    });
    env['finally'] = bind$(this, 'finally');
    this['let']('env', env);
    (yield this.get('destroy'));
    (yield ui.waitFor(bind$(container, 'fadeOut')));
    container.empty();
    if (window.gc != null) {
      window.gc();
    }
  });
  out$.runScenario = runScenario = seqr.bind(function*(scenarioLoader) {
    var args,
        res$,
        i$,
        to$,
        scope,
        env,
        scenario,
        intro,
        me,
        scene,
        renderer,
        render,
        el,
        done,
        result,
        ref$,
        passed,
        outro;
    res$ = [];
    for (i$ = 1, to$ = arguments.length; i$ < to$; ++i$) {
      res$.push(arguments[i$]);
    }
    args = res$;
    scope = newEnv();
    env = (yield scope.get('env'));
    this['let']('env', env);
    env.notifications = $('<div class="notifications">').appendTo(env.container);
    env.logger.write({loadingScenario: scenarioLoader.scenarioName});
    scenario = scenarioLoader.apply(null, [env].concat(slice$.call(args)));
    intro = P.resolve(undefined);
    me = this;
    scenario.get('intro').then(function(introContent) {
      return intro = ui.instructionScreen(env, function() {
        this('title').append(introContent.title);
        this('subtitle').append(introContent.subtitle);
        this('content').append(introContent.content);
        env.logger.write({scenarioIntro: this.el.html()});
        return me.get('ready');
      });
    });
    scene = (yield scenario.get('scene'));
    renderer = env.renderer = new THREE.WebGLRenderer({antialias: true});
    this['finally'](function() {
      THREE.Cache.clear();
      return (new CANNON.World).step(1 / 60);
    });
    renderer.autoClear = false;
    scene.beforeRender.add(function() {
      return renderer.clear();
    });
    render = function() {
      return renderer.render(scene.visual, scene.camera);
    };
    if (env.opts.enableVr) {
      render = enableVr(env, renderer, scene);
    }
    scene.onRender.add(render);
    scene.onTickHandled(function() {
      var dump,
          ref$;
      dump = {
        sceneTime: scene.time,
        physics: dumpPhysics(scene.physics),
        camera: {
          matrixWorldInverse: scene.camera.matrixWorldInverse.toArray(),
          projectionMatrix: scene.camera.projectionMatrix.toArray()
        },
        telemetry: {
          throttle: (ref$ = env.controls).throttle,
          brake: ref$.brake,
          steering: ref$.steering,
          direction: ref$.direction
        }
      };
      return env.logger.write(dump);
    });
    env.onSize(function(w, h) {
      renderer.setSize(w, h);
      scene.camera.aspect = w / h;
      scene.camera.updateProjectionMatrix();
      return render();
    });
    el = $(renderer.domElement);
    el.hide();
    env.container.append(el);
    (yield P.resolve(scene.preroll()));
    (yield ui.waitFor(bind$(el, 'fadeIn')));
    this['let']('ready', [scenario]);
    this['let']('intro', [intro]);
    (yield intro);
    scenario['let']('run');
    done = scenario.get('done');
    env.logger.write({startingScenario: scenarioLoader.scenarioName});
    scene.onStart.dispatch();
    (yield eachFrame(function(dt) {
      if (!done.isPending()) {
        return true;
      }
      scene.tick(dt);
    }));
    scene.onExit.dispatch();
    env.logger.write({exitedScenario: scenarioLoader.scenarioName});
    env.notifications.fadeOut();
    (yield ui.waitFor(bind$(el, 'fadeOut')));
    ref$ = result = (yield scenario), passed = ref$.passed, outro = ref$.outro;
    el.remove();
    outro = ui.instructionScreen(env, function() {
      this('title').append(outro.title);
      this('subtitle').append(outro.subtitle);
      this('content').append(outro.content);
      return me['let']('done', {
        passed: passed,
        outro: this,
        result: result
      });
    });
    this['let']('outro', [outro]);
    (yield outro);
    scope['let']('destroy');
    (yield scope);
    env.logger.write({destroyedScenario: scenarioLoader.scenarioName});
  });
  function clone$(it) {
    function fun() {}
    fun.prototype = it;
    return new fun;
  }
  function import$(obj, src) {
    var own = {}.hasOwnProperty;
    for (var key in src)
      if (own.call(src, key))
        obj[key] = src[key];
    return obj;
  }
  function bind$(obj, key, target) {
    return function() {
      return (target || obj)[key].apply(obj, arguments);
    };
  }
  return module.exports;
});

$__System.registerDynamic("27", [], false, function($__require, $__exports, $__module) {
  var _retrieveGlobal = $__System.get("@@global-helpers").prepareGlobal($__module.id, null, null);
  (function() {
    (function(global) {
      var module = global.noise = {};
      function Grad(x, y, z) {
        this.x = x;
        this.y = y;
        this.z = z;
      }
      Grad.prototype.dot2 = function(x, y) {
        return this.x * x + this.y * y;
      };
      Grad.prototype.dot3 = function(x, y, z) {
        return this.x * x + this.y * y + this.z * z;
      };
      var grad3 = [new Grad(1, 1, 0), new Grad(-1, 1, 0), new Grad(1, -1, 0), new Grad(-1, -1, 0), new Grad(1, 0, 1), new Grad(-1, 0, 1), new Grad(1, 0, -1), new Grad(-1, 0, -1), new Grad(0, 1, 1), new Grad(0, -1, 1), new Grad(0, 1, -1), new Grad(0, -1, -1)];
      var p = [151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 196, 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, 218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180];
      var perm = new Array(512);
      var gradP = new Array(512);
      module.seed = function(seed) {
        if (seed > 0 && seed < 1) {
          seed *= 65536;
        }
        seed = Math.floor(seed);
        if (seed < 256) {
          seed |= seed << 8;
        }
        for (var i = 0; i < 256; i++) {
          var v;
          if (i & 1) {
            v = p[i] ^ (seed & 255);
          } else {
            v = p[i] ^ ((seed >> 8) & 255);
          }
          perm[i] = perm[i + 256] = v;
          gradP[i] = gradP[i + 256] = grad3[v % 12];
        }
      };
      module.seed(0);
      var F2 = 0.5 * (Math.sqrt(3) - 1);
      var G2 = (3 - Math.sqrt(3)) / 6;
      var F3 = 1 / 3;
      var G3 = 1 / 6;
      module.simplex2 = function(xin, yin) {
        var n0,
            n1,
            n2;
        var s = (xin + yin) * F2;
        var i = Math.floor(xin + s);
        var j = Math.floor(yin + s);
        var t = (i + j) * G2;
        var x0 = xin - i + t;
        var y0 = yin - j + t;
        var i1,
            j1;
        if (x0 > y0) {
          i1 = 1;
          j1 = 0;
        } else {
          i1 = 0;
          j1 = 1;
        }
        var x1 = x0 - i1 + G2;
        var y1 = y0 - j1 + G2;
        var x2 = x0 - 1 + 2 * G2;
        var y2 = y0 - 1 + 2 * G2;
        i &= 255;
        j &= 255;
        var gi0 = gradP[i + perm[j]];
        var gi1 = gradP[i + i1 + perm[j + j1]];
        var gi2 = gradP[i + 1 + perm[j + 1]];
        var t0 = 0.5 - x0 * x0 - y0 * y0;
        if (t0 < 0) {
          n0 = 0;
        } else {
          t0 *= t0;
          n0 = t0 * t0 * gi0.dot2(x0, y0);
        }
        var t1 = 0.5 - x1 * x1 - y1 * y1;
        if (t1 < 0) {
          n1 = 0;
        } else {
          t1 *= t1;
          n1 = t1 * t1 * gi1.dot2(x1, y1);
        }
        var t2 = 0.5 - x2 * x2 - y2 * y2;
        if (t2 < 0) {
          n2 = 0;
        } else {
          t2 *= t2;
          n2 = t2 * t2 * gi2.dot2(x2, y2);
        }
        return 70 * (n0 + n1 + n2);
      };
      module.simplex3 = function(xin, yin, zin) {
        var n0,
            n1,
            n2,
            n3;
        var s = (xin + yin + zin) * F3;
        var i = Math.floor(xin + s);
        var j = Math.floor(yin + s);
        var k = Math.floor(zin + s);
        var t = (i + j + k) * G3;
        var x0 = xin - i + t;
        var y0 = yin - j + t;
        var z0 = zin - k + t;
        var i1,
            j1,
            k1;
        var i2,
            j2,
            k2;
        if (x0 >= y0) {
          if (y0 >= z0) {
            i1 = 1;
            j1 = 0;
            k1 = 0;
            i2 = 1;
            j2 = 1;
            k2 = 0;
          } else if (x0 >= z0) {
            i1 = 1;
            j1 = 0;
            k1 = 0;
            i2 = 1;
            j2 = 0;
            k2 = 1;
          } else {
            i1 = 0;
            j1 = 0;
            k1 = 1;
            i2 = 1;
            j2 = 0;
            k2 = 1;
          }
        } else {
          if (y0 < z0) {
            i1 = 0;
            j1 = 0;
            k1 = 1;
            i2 = 0;
            j2 = 1;
            k2 = 1;
          } else if (x0 < z0) {
            i1 = 0;
            j1 = 1;
            k1 = 0;
            i2 = 0;
            j2 = 1;
            k2 = 1;
          } else {
            i1 = 0;
            j1 = 1;
            k1 = 0;
            i2 = 1;
            j2 = 1;
            k2 = 0;
          }
        }
        var x1 = x0 - i1 + G3;
        var y1 = y0 - j1 + G3;
        var z1 = z0 - k1 + G3;
        var x2 = x0 - i2 + 2 * G3;
        var y2 = y0 - j2 + 2 * G3;
        var z2 = z0 - k2 + 2 * G3;
        var x3 = x0 - 1 + 3 * G3;
        var y3 = y0 - 1 + 3 * G3;
        var z3 = z0 - 1 + 3 * G3;
        i &= 255;
        j &= 255;
        k &= 255;
        var gi0 = gradP[i + perm[j + perm[k]]];
        var gi1 = gradP[i + i1 + perm[j + j1 + perm[k + k1]]];
        var gi2 = gradP[i + i2 + perm[j + j2 + perm[k + k2]]];
        var gi3 = gradP[i + 1 + perm[j + 1 + perm[k + 1]]];
        var t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0;
        if (t0 < 0) {
          n0 = 0;
        } else {
          t0 *= t0;
          n0 = t0 * t0 * gi0.dot3(x0, y0, z0);
        }
        var t1 = 0.6 - x1 * x1 - y1 * y1 - z1 * z1;
        if (t1 < 0) {
          n1 = 0;
        } else {
          t1 *= t1;
          n1 = t1 * t1 * gi1.dot3(x1, y1, z1);
        }
        var t2 = 0.6 - x2 * x2 - y2 * y2 - z2 * z2;
        if (t2 < 0) {
          n2 = 0;
        } else {
          t2 *= t2;
          n2 = t2 * t2 * gi2.dot3(x2, y2, z2);
        }
        var t3 = 0.6 - x3 * x3 - y3 * y3 - z3 * z3;
        if (t3 < 0) {
          n3 = 0;
        } else {
          t3 *= t3;
          n3 = t3 * t3 * gi3.dot3(x3, y3, z3);
        }
        return 32 * (n0 + n1 + n2 + n3);
      };
      function fade(t) {
        return t * t * t * (t * (t * 6 - 15) + 10);
      }
      function lerp(a, b, t) {
        return (1 - t) * a + t * b;
      }
      module.perlin2 = function(x, y) {
        var X = Math.floor(x),
            Y = Math.floor(y);
        x = x - X;
        y = y - Y;
        X = X & 255;
        Y = Y & 255;
        var n00 = gradP[X + perm[Y]].dot2(x, y);
        var n01 = gradP[X + perm[Y + 1]].dot2(x, y - 1);
        var n10 = gradP[X + 1 + perm[Y]].dot2(x - 1, y);
        var n11 = gradP[X + 1 + perm[Y + 1]].dot2(x - 1, y - 1);
        var u = fade(x);
        return lerp(lerp(n00, n10, u), lerp(n01, n11, u), fade(y));
      };
      module.perlin3 = function(x, y, z) {
        var X = Math.floor(x),
            Y = Math.floor(y),
            Z = Math.floor(z);
        x = x - X;
        y = y - Y;
        z = z - Z;
        X = X & 255;
        Y = Y & 255;
        Z = Z & 255;
        var n000 = gradP[X + perm[Y + perm[Z]]].dot3(x, y, z);
        var n001 = gradP[X + perm[Y + perm[Z + 1]]].dot3(x, y, z - 1);
        var n010 = gradP[X + perm[Y + 1 + perm[Z]]].dot3(x, y - 1, z);
        var n011 = gradP[X + perm[Y + 1 + perm[Z + 1]]].dot3(x, y - 1, z - 1);
        var n100 = gradP[X + 1 + perm[Y + perm[Z]]].dot3(x - 1, y, z);
        var n101 = gradP[X + 1 + perm[Y + perm[Z + 1]]].dot3(x - 1, y, z - 1);
        var n110 = gradP[X + 1 + perm[Y + 1 + perm[Z]]].dot3(x - 1, y - 1, z);
        var n111 = gradP[X + 1 + perm[Y + 1 + perm[Z + 1]]].dot3(x - 1, y - 1, z - 1);
        var u = fade(x);
        var v = fade(y);
        var w = fade(z);
        return lerp(lerp(lerp(n000, n100, u), lerp(n001, n101, u), w), lerp(lerp(n010, n110, u), lerp(n011, n111, u), w), v);
      };
    })(this);
  })();
  return _retrieveGlobal();
});

$__System.registerDynamic("28", ["26", "21", "29", "20", "1a", "2a", "27", "25"], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  var Cannon,
      Signal,
      jStat,
      P,
      Co,
      seqr,
      ref$,
      loadCollada,
      mergeObject,
      perlin,
      THREE,
      Scene,
      generateRock,
      addGround,
      out$ = typeof exports != 'undefined' && exports || this;
  Cannon = $__require('26');
  Signal = $__require('21').Signal;
  jStat = $__require('29');
  P = $__require('20');
  Co = P.coroutine;
  seqr = $__require('1a');
  ref$ = $__require('2a'), loadCollada = ref$.loadCollada, mergeObject = ref$.mergeObject;
  perlin = $__require('27');
  THREE = $__require('25');
  out$.Scene = Scene = (function() {
    Scene.displayName = 'Scene';
    var prototype = Scene.prototype,
        constructor = Scene;
    function Scene(arg$) {
      var ref$,
          ref1$,
          x$,
          y$,
          this$ = this;
      ref$ = arg$ != null ? arg$ : {}, this.minStepDuration = (ref1$ = ref$.minStepDuration) != null ? ref1$ : 1 / 60, this.camera = ref$.camera, this.visual = ref$.visual, this.physics = ref$.physics;
      this.beforePhysics = new Signal;
      this.onPhysics = new Signal;
      this.afterPhysics = new Signal;
      this.beforeRender = new Signal;
      this.onRender = new Signal;
      this.afterRender = new Signal;
      this.onTickHandled = new Signal;
      this.onStart = new Signal;
      this.onExit = new Signal;
      x$ = (ref$ = this.physics) != null ? ref$ : this.physics = new Cannon.World;
      x$.gravity.set(0, -9.81, 0);
      y$ = x$.defaultContactMaterial;
      y$.friction = 0.7;
      y$.restitution = 0.3;
      x$.solver.iterations = 100;
      x$.broadphase = new Cannon.SAPBroadphase(this.physics);
      this.visual == null && (this.visual = new THREE.Scene);
      this.camera == null && (this.camera = new THREE.PerspectiveCamera(65 / (16 / 9), 1, 0.01, 450000));
      this.time = 0;
      this.onPhysics.add(function(dt) {
        var nSteps,
            stepdur;
        nSteps = Math.ceil(dt / this$.minStepDuration);
        stepdur = dt / nSteps;
        return this$.physics.step(stepdur, dt, nSteps);
      });
    }
    Scene.prototype.tick = function(dt) {
      this.beforePhysics.dispatch(dt, this.time);
      this.onPhysics.dispatch(dt, this.time);
      this.afterPhysics.dispatch(dt, this.time);
      this.beforeRender.dispatch(dt, this.time);
      this.onRender.dispatch(dt, this.time);
      this.afterRender.dispatch(dt, this.time);
      this.time += dt;
      return this.onTickHandled.dispatch(dt, this.time);
    };
    Scene.prototype.bindPhys = function(physical, visual) {
      return this.afterPhysics.add(function() {
        visual.position.copy(physical.position);
        return visual.quaternion.copy(physical.quaternion);
      });
    };
    return Scene;
  }());
  generateRock = function(seed) {
    var radius,
        scale,
        noiseScale,
        geo,
        dir,
        i$,
        ref$,
        len$,
        vert,
        rnd,
        rock;
    seed == null && (seed = Math.random());
    perlin.seed(seed);
    radius = 1;
    scale = radius;
    noiseScale = 100;
    geo = new THREE.IcosahedronGeometry(radius, 1);
    dir = new THREE.Vector3;
    for (i$ = 0, len$ = (ref$ = geo.vertices).length; i$ < len$; ++i$) {
      vert = ref$[i$];
      dir.copy(vert);
      dir.normalize();
      rnd = perlin.simplex3(vert.x * noiseScale, vert.y * noiseScale, vert.z * noiseScale) * scale;
      dir.multiplyScalar(Math.abs(rnd) * scale);
      vert.add(dir);
    }
    geo.verticesNeedUpdate = true;
    geo.computeVertexNormals();
    geo.computeFaceNormals();
    rock = new THREE.Mesh(geo, new THREE.MeshLambertMaterial({color: 0xd3ab6d}));
    rock.castShadow = true;
    rock.receiveShadow = true;
    return rock;
  };
  out$.addGround = addGround = function(scene) {
    var groundTex,
        terrainSize,
        textureSize,
        textureRep,
        groundNorm,
        groundMaterial,
        terrain,
        groundGeometry,
        ground,
        x$,
        groundBody,
        roadWidth,
        roadGeo,
        roadTex,
        roadNorm,
        roadMat,
        road,
        rocks,
        nRockTypes,
        rockPool,
        res$,
        i$,
        i,
        randomRock,
        nRocks,
        sizeDist,
        zDist,
        xDist,
        x,
        size,
        z,
        rock,
        ahead,
        behind,
        position;
    groundTex = THREE.ImageUtils.loadTexture('res/world/sandtexture.jpg');
    terrainSize = 1000;
    textureSize = 5;
    textureRep = terrainSize / textureSize;
    groundNorm = THREE.ImageUtils.loadTexture('res/world/sandtexture.norm.jpg');
    groundTex.wrapS = groundTex.wrapT = THREE.RepeatWrapping;
    groundNorm.wrapS = groundNorm.wrapT = THREE.RepeatWrapping;
    groundTex.repeat.set(textureRep, textureRep);
    groundNorm.repeat.set(textureRep, textureRep);
    groundTex.anisotropy = 12;
    groundMaterial = new THREE.MeshPhongMaterial({
      color: 0xffffff,
      map: groundTex,
      normalMap: groundNorm,
      shininess: 20
    });
    terrain = new THREE.Object3D;
    terrain.receiveShadow = true;
    groundGeometry = new THREE.PlaneGeometry(terrainSize, terrainSize, 0, 0);
    ground = new THREE.Mesh(groundGeometry, groundMaterial);
    ground.castShadow = false;
    ground.receiveShadow = true;
    ground.rotation.x = -Math.PI / 2.0;
    ground.position.y = -0.1;
    x$ = groundBody = new Cannon.Body({mass: 0});
    x$.addShape(new Cannon.Plane);
    x$.quaternion.setFromAxisAngle(new Cannon.Vec3(1, 0, 0), -Math.PI / 2.0);
    terrain.add(ground);
    scene.physics.add(groundBody);
    roadWidth = 7;
    roadGeo = new THREE.PlaneGeometry(terrainSize, roadWidth, 0, 0);
    roadTex = THREE.ImageUtils.loadTexture('res/world/road_texture.jpg');
    roadNorm = THREE.ImageUtils.loadTexture('res/world/road_texture.norm.jpg');
    roadTex.anisotropy = 12;
    roadTex.minFilter = THREE.LinearFilter;
    roadTex.wrapS = roadTex.wrapT = THREE.RepeatWrapping;
    roadNorm.wrapS = roadNorm.wrapT = THREE.RepeatWrapping;
    roadTex.repeat.set(textureRep / 2.0, 1);
    roadNorm.repeat.set(textureRep / 2.0, 1);
    roadMat = new THREE.MeshPhongMaterial({
      map: roadTex,
      shininess: 20,
      normalMap: roadNorm
    });
    road = new THREE.Mesh(roadGeo, roadMat);
    road.rotation.x = -Math.PI / 2.0;
    road.rotation.z = -Math.PI / 2.0;
    road.position.y = 0;
    terrain.add(road);
    rocks = new THREE.Object3D();
    nRockTypes = 10;
    res$ = [];
    for (i$ = 0; i$ < nRockTypes; ++i$) {
      i = i$;
      res$.push(generateRock());
    }
    rockPool = res$;
    randomRock = function() {
      var rock;
      rock = rockPool[Math.floor(Math.random() * rockPool.length)];
      return new THREE.Mesh(rock.geometry, rock.material);
    };
    nRocks = Math.round(terrainSize * (2 * 200) / 500);
    sizeDist = jStat.uniform(0.1, 0.6);
    zDist = jStat.uniform(-terrainSize / 2, terrainSize / 2);
    xDist = jStat.uniform(-200, 200);
    for (i$ = 0; i$ < nRocks; ++i$) {
      i = i$;
      x = xDist.sample();
      size = sizeDist.sample();
      if (Math.abs(x) - Math.abs(size) < roadWidth) {
        continue;
      }
      z = zDist.sample();
      rock = randomRock();
      rock.position.x = x;
      rock.position.z = z;
      rock.scale.multiplyScalar(size);
      rock.scale.y *= 0.8;
      rock.updateMatrix();
      rock.matrixAutoUpdate = false;
      rocks.add(rock);
    }
    terrain.add(mergeObject(rocks));
    scene.visual.add(terrain);
    ahead = terrain.clone();
    behind = terrain.clone();
    scene.visual.add(ahead);
    scene.visual.add(behind);
    position = new THREE.Vector3;
    return scene.beforeRender.add(function() {
      var nTerrains;
      position.setFromMatrixPosition(scene.camera.matrixWorld);
      nTerrains = Math.floor((position.z + terrainSize / 2.0) / terrainSize);
      terrain.position.z = nTerrains * terrainSize;
      ahead.position.z = terrain.position.z + terrainSize;
      return behind.position.z = terrain.position.z - terrainSize;
    });
  };
  return module.exports;
});

$__System.registerDynamic("2b", ["20"], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  var Promise,
      PLoader,
      out$ = typeof exports != 'undefined' && exports || this,
      slice$ = [].slice;
  Promise = $__require('20');
  out$.PLoader = PLoader = function(LoaderCls) {
    var loader;
    loader = new LoaderCls;
    return function() {
      var args,
          res$,
          i$,
          to$;
      res$ = [];
      for (i$ = 0, to$ = arguments.length; i$ < to$; ++i$) {
        res$.push(arguments[i$]);
      }
      args = res$;
      return new Promise(function(resolve, reject) {
        return loader.load.apply(loader, slice$.call(args).concat([function() {
          var args,
              res$,
              i$,
              to$;
          res$ = [];
          for (i$ = 0, to$ = arguments.length; i$ < to$; ++i$) {
            res$.push(arguments[i$]);
          }
          args = res$;
          return resolve(args);
        }]));
      });
    };
  };
  return module.exports;
});

$__System.registerDynamic("2c", ["20", "2b", "25", "2d", "26", "21", "2a"], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  var P,
      Co,
      PLoader,
      THREE,
      Cannon,
      Signal,
      ref$,
      loadCollada,
      mergeObject,
      DummyControls,
      loadCorolla,
      loadViva,
      addVehicle,
      out$ = typeof exports != 'undefined' && exports || this;
  P = $__require('20');
  Co = P.coroutine;
  PLoader = $__require('2b').PLoader;
  THREE = $__require('25');
  window.THREE = THREE;
  $__require('2d');
  Cannon = $__require('26');
  Signal = $__require('21').Signal;
  ref$ = $__require('2a'), loadCollada = ref$.loadCollada, mergeObject = ref$.mergeObject;
  DummyControls = (function() {
    DummyControls.displayName = 'DummyControls';
    var prototype = DummyControls.prototype,
        constructor = DummyControls;
    function DummyControls() {
      this.throttle = 0;
      this.brake = 0;
      this.steering = 0;
      this.direction = 1;
    }
    DummyControls.prototype.set = function() {};
    return DummyControls;
  }());
  loadCorolla = Co(function*() {
    var vehicle,
        scene,
        body,
        eye;
    vehicle = (yield loadCollada('res/corolla/body.dae'));
    scene = vehicle.scene;
    scene.traverse(function(obj) {
      if (obj.material == null) {
        return;
      }
      return obj.material.side = THREE.DoubleSide;
    });
    body = scene.getObjectByName("Body");
    eye = new THREE.Object3D;
    eye.position.y = 0.1;
    eye.position.z = 0.3;
    eye.rotation.y = Math.PI;
    body.getObjectByName("DriverHeadrest").add(eye);
    return {
      body: body,
      wheels: scene.getObjectByName("Wheels"),
      eye: eye
    };
  });
  loadViva = Co(function*() {
    var vehicle,
        scene,
        car,
        centerXz,
        originToGeometry,
        applyPosition,
        body,
        brakeLightMaterials,
        eye,
        wheels,
        i$,
        ref$,
        len$;
    vehicle = (yield loadCollada("res/viva/2006-VIVA-VT3-Sedan-SE.dae"));
    scene = vehicle.scene;
    car = scene.getObjectByName("Car");
    centerXz = function(obj) {
      var bbox,
          offcenter,
          shift,
          i$,
          ref$,
          len$,
          child;
      obj.updateMatrixWorld(true);
      bbox = (new THREE.Box3).setFromObject(obj);
      offcenter = bbox.max.add(bbox.min).divideScalar(2);
      shift = offcenter.sub(obj.position);
      shift.y = 0;
      obj.position.x = 0;
      obj.position.z = 0;
      for (i$ = 0, len$ = (ref$ = obj.children).length; i$ < len$; ++i$) {
        child = ref$[i$];
        child.position.sub(shift);
      }
      return obj.updateMatrixWorld(true);
    };
    originToGeometry = function(obj) {
      var i$,
          ref$,
          len$,
          child,
          bbox,
          newOrigin,
          currentPos,
          shift;
      if (obj.parent != null) {
        obj.parent.updateMatrixWorld(true);
        obj.applyMatrix(obj.parent.matrixWorld);
        obj.parent = null;
      }
      obj.updateMatrixWorld(true);
      for (i$ = 0, len$ = (ref$ = obj.children).length; i$ < len$; ++i$) {
        child = ref$[i$];
        child.applyMatrix(obj.matrix);
      }
      obj.position.set(0, 0, 0);
      obj.rotation.set(0, 0, 0);
      obj.scale.set(1, 1, 1);
      obj.updateMatrix();
      obj.updateMatrixWorld(true);
      bbox = (new THREE.Box3).setFromObject(obj);
      newOrigin = bbox.max.add(bbox.min).divideScalar(2);
      currentPos = obj.position;
      shift = newOrigin.clone().sub(currentPos);
      obj.position.copy(newOrigin);
      for (i$ = 0, len$ = (ref$ = obj.children).length; i$ < len$; ++i$) {
        child = ref$[i$];
        child.position.sub(shift);
      }
      return obj.updateMatrixWorld(true);
    };
    applyPosition = function(obj) {
      var pos,
          i$,
          ref$,
          len$,
          child;
      obj.updateMatrixWorld(true);
      pos = obj.position.clone();
      obj.position.set(0, 0, 0);
      for (i$ = 0, len$ = (ref$ = obj.children).length; i$ < len$; ++i$) {
        child = ref$[i$];
        child.position.add(pos);
      }
      return obj.updateMatrixWorld(true);
    };
    centerXz(car);
    applyPosition(car);
    body = car.getObjectByName("Body");
    applyPosition(body);
    body = mergeObject(body);
    brakeLightMaterials = [];
    body.traverse(function(obj) {
      var i$,
          ref$,
          ref1$,
          len$,
          material,
          results$ = [];
      if (obj.material == null) {
        return;
      }
      for (i$ = 0, len$ = (ref$ = (ref1$ = obj.material.materials) != null ? ref1$ : [obj.material]).length; i$ < len$; ++i$) {
        material = ref$[i$];
        if (material.name === 'Red') {
          results$.push(brakeLightMaterials.push(material));
        }
      }
      return results$;
    });
    eye = new THREE.Object3D;
    eye.position.y = 1.23;
    eye.position.z = 0.1;
    eye.position.x = 0.37;
    eye.rotation.y = Math.PI;
    body.add(eye);
    wheels = scene.getObjectByName("Wheels");
    for (i$ = 0, len$ = (ref$ = wheels.children).length; i$ < len$; ++i$) {
      (fn$.call(this, ref$[i$]));
    }
    return {
      body: body,
      wheels: wheels,
      eye: eye,
      setBrakelight: function(isOn) {
        var i$,
            ref$,
            len$,
            material,
            results$ = [];
        for (i$ = 0, len$ = (ref$ = brakeLightMaterials).length; i$ < len$; ++i$) {
          material = ref$[i$];
          if (isOn) {
            material.emissive.r = 200;
          } else {
            material.emissive.r = 0;
          }
          results$.push(material.needsUpdate = true);
        }
        return results$;
      }
    };
    function fn$(wheel) {
      originToGeometry(wheel);
      wheel.position.y += 0.1;
    }
  });
  out$.addVehicle = addVehicle = Co(function*(scene, controls, arg$) {
    var objectName,
        ref$,
        body,
        wheels,
        eye,
        setBrakelight,
        syncModels,
        cogY,
        bbox,
        halfbox,
        offOrigin,
        x$,
        bodyPhys,
        car,
        enginePower,
        brakePower,
        brakeExponent,
        brakeResponse,
        maxSteer,
        maxCentering,
        maxCenteringSpeed,
        steeringDeadzone,
        i$,
        len$,
        onCollision;
    controls == null && (controls = new DummyControls);
    objectName = (arg$ != null ? arg$ : {}).objectName;
    ref$ = (yield loadViva()), body = ref$.body, wheels = ref$.wheels, eye = ref$.eye, setBrakelight = ref$.setBrakelight;
    syncModels = new Signal;
    cogY = 0.5;
    scene.visual.add(body);
    bbox = new THREE.Box3().setFromObject(body);
    bbox.min.y += 0.3;
    halfbox = new Cannon.Vec3().copy(bbox.max.clone().sub(bbox.min).divideScalar(2));
    offOrigin = new Cannon.Vec3().copy(bbox.min.clone().add(bbox.max).divideScalar(2));
    offOrigin.y -= cogY;
    x$ = bodyPhys = new Cannon.Body({mass: 2000});
    x$.addShape(new Cannon.Box(halfbox), offOrigin);
    x$.linearDamping = 0.1;
    x$.angularDamping = 0.1;
    x$.objectName = objectName;
    x$.objectClass = 'vehicle';
    car = new Cannon.RaycastVehicle({
      chassisBody: bodyPhys,
      indexRightAxis: 0,
      indexForwardAxis: 2,
      indexUpAxis: 1
    });
    enginePower = 6000;
    brakePower = 1000;
    brakeExponent = 2000;
    brakeResponse = function(pedal) {
      return (Math.pow(brakeExponent, pedal) - 1) / brakeExponent * brakePower;
    };
    maxSteer = 0.8;
    maxCentering = 0.4;
    maxCenteringSpeed = 10;
    steeringDeadzone = 0.005;
    controls.set({autocenter: 0.6});
    wheels = wheels.children;
    for (i$ = 0, len$ = wheels.length; i$ < len$; ++i$) {
      (fn$.call(this, wheels[i$]));
    }
    syncModels.add(function() {
      body.position.copy(bodyPhys.position);
      body.position.y -= cogY;
      body.quaternion.copy(bodyPhys.quaternion);
      return body.updateMatrixWorld();
    });
    scene.afterPhysics.add(function() {
      return syncModels.dispatch();
    });
    car.addToWorld(scene.physics);
    scene.onExit(function() {
      return car.removeFromWorld(scene.physics);
    });
    bodyPhys.position.y = 2;
    onCollision = Signal();
    bodyPhys.addEventListener("collide", function(e) {
      var ref$;
      if (typeof(ref$ = e.body).preventCollisionEvent == 'function' && ref$.preventCollisionEvent(e)) {
        return;
      }
      return onCollision.dispatch(e);
    });
    return {
      getSpeed: function() {
        if (car.currentVehicleSpeedKmHour == null) {
          return 0;
        }
        return car.currentVehicleSpeedKmHour / 3.6;
      },
      eye: eye,
      physical: bodyPhys,
      body: body,
      forceModelSync: function() {
        return syncModels.dispatch();
      },
      controls: controls,
      onCollision: onCollision
    };
    function fn$(wheel) {
      var wbb,
          wRadius,
          ref$,
          x,
          y,
          z,
          wii,
          wi;
      wheel = wheel.clone();
      wbb = (new THREE.Box3).setFromObject(wheel);
      wRadius = (wbb.max.z - wbb.min.z) / 2.0;
      ref$ = wheel.position, x = ref$.x, y = ref$.y, z = ref$.z;
      wii = car.addWheel({
        radius: wRadius,
        directionLocal: new Cannon.Vec3(0, -1, 0),
        axleLocal: new Cannon.Vec3(-1, 0, 0),
        suspensionRestLength: wRadius + 0.35,
        chassisConnectionPointLocal: new Cannon.Vec3(x, y, z),
        suspensionStiffness: 40,
        rollInfluence: 1,
        frictionSlip: 1
      });
      wi = car.wheelInfos[wii];
      scene.visual.add(wheel);
      syncModels.add(function() {
        car.updateWheelTransform(wii);
        wheel.position.copy(wi.worldTransform.position);
        return wheel.quaternion.copy(wi.worldTransform.quaternion);
      });
      scene.beforePhysics.add(function() {
        var mag,
            dir,
            steering;
        setBrakelight(controls.brake > 0);
        mag = Math.abs(controls.steering);
        dir = Math.sign(controls.steering);
        mag -= steeringDeadzone;
        mag = Math.max(mag, 0);
        steering = mag * dir * maxSteer;
        if (z > 0) {
          wi.brake = brakeResponse(controls.brake);
          return wi.steering = maxSteer * steering;
        } else {
          return wi.engineForce = -enginePower * controls.throttle * controls.direction;
        }
      });
    }
  });
  return module.exports;
});

$__System.registerDynamic("22", ["20", "19", "21"], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  var P,
      $,
      Signal,
      WsController,
      KeyboardController,
      NonSteeringControl,
      TargetSpeedController,
      out$ = typeof exports != 'undefined' && exports || this;
  P = $__require('20');
  $ = $__require('19');
  Signal = $__require('21').Signal;
  out$.WsController = WsController = (function() {
    WsController.displayName = 'WsController';
    var prototype = WsController.prototype,
        constructor = WsController;
    WsController.Connect = function(url) {
      return new P(function(resolve, reject) {
        var socket;
        socket = new WebSocket(url);
        return socket.onopen = function() {
          return resolve(new WsController(socket));
        };
      });
    };
    function WsController(socket) {
      var this$ = this;
      this.socket = socket;
      this.throttle = 0;
      this.brake = 0;
      this.steering = 0;
      this.direction = 1;
      this.change = new Signal;
      this.socket.onmessage = function(msg) {
        var event,
            key,
            value;
        event = JSON.parse(msg.data);
        for (key in event) {
          value = event[key];
          this$.change.dispatch(key, value);
        }
        return import$(this$, event);
      };
    }
    WsController.prototype.set = function(obj) {
      return this.socket.send(JSON.stringify(obj));
    };
    WsController.prototype.close = function() {
      this.socket.onmessage = null;
      return this.socket.close();
    };
    return WsController;
  }());
  out$.KeyboardController = KeyboardController = (function() {
    KeyboardController.displayName = 'KeyboardController';
    var prototype = KeyboardController.prototype,
        constructor = KeyboardController;
    function KeyboardController() {
      var changeSpeed,
          nudge,
          prevTime,
          tick,
          UP,
          DOWN,
          SPACE,
          LEFT,
          RIGHT,
          CTRL,
          this$ = this;
      this.throttle = 0;
      this.brake = 0;
      this.steering = 0;
      this.direction = 1;
      this.throttleTarget = 0;
      this.brakeTarget = 0;
      this.steeringLeft = 0;
      this.steeringRight = 0;
      this.up = 0;
      this.down = 0;
      this.left = 0;
      this.right = 0;
      changeSpeed = 2;
      nudge = function(dt, name, target) {
        var diff,
            change;
        if (!isFinite(dt)) {
          return;
        }
        diff = target - this$[name];
        change = dt * changeSpeed * Math.sign(diff);
        if (diff < 0) {
          change = Math.max(change, diff);
        } else {
          change = Math.min(change, diff);
        }
        return this$[name] += change;
      };
      this._closed = false;
      prevTime = undefined;
      tick = function() {
        var time,
            dt;
        if (this$._closed) {
          return;
        }
        time = Date.now();
        dt = (time - prevTime) / 1000;
        prevTime = time;
        nudge(dt, 'throttle', this$.throttleTarget);
        nudge(dt, 'brake', this$.brakeTarget);
        nudge(dt, 'steering', this$.steeringLeft - this$.steeringRight);
        return requestAnimationFrame(tick);
      };
      tick();
      this.change = new Signal;
      UP = 38;
      DOWN = 40;
      SPACE = 32;
      LEFT = 37;
      RIGHT = 39;
      CTRL = 17;
      $("body").keydown(this._keydown = function(e) {
        switch (e.which) {
          case UP:
            this$.throttleTarget = 1;
            return this$._update('up', 1);
          case DOWN:
            this$.brakeTarget = 1;
            return this$._update('down', 1);
          case LEFT:
            this$.steeringLeft = 1;
            return this$._update('left', 1);
          case RIGHT:
            this$.steeringRight = 1;
            return this$._update('right', 1);
          case CTRL:
            return this$._update('blinder', true);
          case SPACE:
            return this$._update('catch', true);
        }
      }).keyup(this._keyup = function(e) {
        switch (e.which) {
          case UP:
            this$.throttleTarget = 0;
            return this$._update('up', 0);
          case DOWN:
            this$.brakeTarget = 0;
            return this$._update('down', 0);
          case LEFT:
            this$.steeringLeft = 0;
            return this$._update('left', 0);
          case RIGHT:
            this$.steeringRight = 0;
            return this$._update('right', 0);
          case CTRL:
            return this$._update('blinder', false);
          case SPACE:
            return this$._update('catch', false);
        }
      });
    }
    KeyboardController.prototype._update = function(key, value) {
      if (this[key] === value) {
        return;
      }
      this.change.dispatch(key, value);
      return this[key] = value;
    };
    KeyboardController.prototype.set = function() {};
    KeyboardController.prototype.close = function() {
      this._closed = true;
      return $("body").off("keydown", this._keydown).off("keyup", this._keyup);
    };
    return KeyboardController;
  }());
  out$.NonSteeringControl = NonSteeringControl = function(orig) {
    var ctrl;
    ctrl = clone$(orig);
    ctrl.steering = 0;
    return ctrl;
  };
  out$.TargetSpeedController = TargetSpeedController = (function() {
    TargetSpeedController.displayName = 'TargetSpeedController';
    var prototype = TargetSpeedController.prototype,
        constructor = TargetSpeedController;
    function TargetSpeedController(target) {
      this.target = target != null ? target : 0;
      this.throttle = 0;
      this.brake = 0;
      this.steering = 0;
      this.direction = 1;
    }
    TargetSpeedController.prototype.tick = function(speed, dt) {
      var delta,
          force;
      delta = this.target - speed;
      force = Math.tanh(delta);
      if (force > 0) {
        this.throttle = force;
        return this.brake = 0;
      } else {
        this.brake = force;
        return this.throttle = 0;
      }
    };
    TargetSpeedController.prototype.set = function() {};
    return TargetSpeedController;
  }());
  function import$(obj, src) {
    var own = {}.hasOwnProperty;
    for (var key in src)
      if (own.call(src, key))
        obj[key] = src[key];
    return obj;
  }
  function clone$(it) {
    function fun() {}
    fun.prototype = it;
    return new fun;
  }
  return module.exports;
});

$__System.registerDynamic("2e", ["19", "20", "1a", "8"], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  var $,
      P,
      seqr,
      ref$,
      sum,
      sortBy,
      zip,
      loadBuffer,
      loadAudio,
      SoundInterpolator,
      DefaultEngineSound,
      BellPlayer,
      NoisePlayer,
      out$ = typeof exports != 'undefined' && exports || this;
  $ = $__require('19');
  P = $__require('20');
  seqr = $__require('1a');
  ref$ = $__require('8'), sum = ref$.sum, sortBy = ref$.sortBy, zip = ref$.zip;
  loadBuffer = function(url) {
    return new Promise(function(accept, reject) {
      var xhr;
      xhr = new XMLHttpRequest();
      xhr.open('GET', url, true);
      xhr.responseType = 'arraybuffer';
      xhr.onload = function(e) {
        return accept(xhr.response);
      };
      xhr.onerror = function(e) {
        return reject(e);
      };
      return xhr.send();
    });
  };
  loadAudio = function(context, url) {
    var p;
    p = loadBuffer(url);
    return p.then(function(data) {
      return new Promise(function(accept, reject) {
        return context.decodeAudioData(data, function(buffer) {
          if (!buffer) {
            reject("Failed to decode '" + url + "'");
          }
          return accept(buffer);
        });
      });
    });
  };
  out$.SoundInterpolator = SoundInterpolator = function(ctx, sampleTbl) {
    return new Promise(function(accept, reject) {
      var sources,
          master,
          value,
          ref$,
          buffer,
          sample,
          source,
          this$ = this;
      sources = [];
      master = ctx.createBiquadFilter();
      master.type = 'lowpass';
      master.frequency.value = 300;
      for (value in ref$ = sampleTbl) {
        buffer = ref$[value];
        sample = ctx.createBufferSource();
        sample.buffer = buffer;
        sample.loop = 1;
        source = ctx.createGain();
        sample.connect(source);
        source.sample = sample;
        sources.push([parseFloat(value), source]);
        source.connect(master);
      }
      sources = sortBy(function(it) {
        return it[0];
      }, sources);
      master.start = function() {
        var i$,
            ref$,
            len$,
            ref1$,
            value,
            source,
            results$ = [];
        for (i$ = 0, len$ = (ref$ = sources).length; i$ < len$; ++i$) {
          ref1$ = ref$[i$], value = ref1$[0], source = ref1$[1];
          results$.push(source.sample.start());
        }
        return results$;
      };
      master.stop = function() {
        var i$,
            ref$,
            len$,
            ref1$,
            value,
            source,
            results$ = [];
        for (i$ = 0, len$ = (ref$ = sources).length; i$ < len$; ++i$) {
          ref1$ = ref$[i$], value = ref1$[0], source = ref1$[1];
          results$.push(source.sample.stop());
        }
        return results$;
      };
      master.setPitch = function(pitch) {
        var gains,
            i$,
            ref$,
            len$,
            ref1$,
            value,
            source,
            totalGain,
            res$,
            gain,
            ref2$,
            results$ = [];
        gains = [];
        for (i$ = 0, len$ = (ref$ = sources).length; i$ < len$; ++i$) {
          ref1$ = ref$[i$], value = ref1$[0], source = ref1$[1];
          gains.push(Math.exp(-Math.abs((value - pitch) / 1000)));
        }
        totalGain = sum(gains);
        res$ = [];
        for (i$ = 0, len$ = gains.length; i$ < len$; ++i$) {
          gain = gains[i$];
          res$.push(gain / totalGain);
        }
        gains = res$;
        for (i$ = 0, len$ = (ref$ = zip(gains, sources)).length; i$ < len$; ++i$) {
          ref1$ = ref$[i$], gain = ref1$[0], ref2$ = ref1$[1], value = ref2$[0], source = ref2$[1];
          source.gain.value = gain;
          results$.push(source.sample.playbackRate.value = pitch / value);
        }
        return results$;
      };
      master.setPitch(sources[0][0]);
      return accept(master);
    });
  };
  out$.DefaultEngineSound = DefaultEngineSound = function(ctx) {
    var f;
    f = function(name) {
      return loadAudio(ctx, "./res/sounds/engine/" + name + ".wav");
    };
    return P.props({
      780: f('idle'),
      1000: f('1000rpm'),
      1700: f('1700rpm'),
      2350: f('2350rpm'),
      2600: f('2600rpm'),
      3000: f('3000rpm')
    }).then(function(samples) {
      return SoundInterpolator(ctx, samples);
    });
  };
  out$.BellPlayer = BellPlayer = seqr.bind(function*(arg$) {
    var audioContext,
        ctx,
        buffer;
    audioContext = arg$.audioContext;
    ctx = audioContext;
    buffer = (yield loadAudio(audioContext, './res/sounds/bell.ogg'));
    return seqr.bind(function*(arg$) {
      var gain,
          ref$,
          sample,
          source;
      gain = (ref$ = (arg$ != null ? arg$ : {}).gain) != null ? ref$ : 1.0;
      sample = ctx.createBufferSource();
      sample.buffer = buffer;
      source = ctx.createGain();
      source.gain.value = gain;
      sample.connect(source);
      source.connect(audioContext.destination);
      sample.start();
      return (yield new P(function(accept) {
        return sample.onended = accept;
      }));
    });
  });
  out$.NoisePlayer = NoisePlayer = seqr.bind(function*(arg$) {
    var audioContext,
        ctx,
        buffer;
    audioContext = arg$.audioContext;
    ctx = audioContext;
    buffer = (yield loadAudio(audioContext, './res/sounds/noiseburst.wav'));
    return seqr.bind(function*(arg$) {
      var gain,
          ref$,
          sample,
          source;
      gain = (ref$ = (arg$ != null ? arg$ : {}).gain) != null ? ref$ : 1.0;
      sample = ctx.createBufferSource();
      sample.buffer = buffer;
      source = ctx.createGain();
      source.gain.value = gain;
      sample.connect(source);
      source.connect(audioContext.destination);
      sample.start();
      return (yield new P(function(accept) {
        return sample.onended = accept;
      }));
    });
  });
  return module.exports;
});

$__System.registerDynamic("26", [], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  !function(e) {
    if ("object" == typeof exports && "undefined" != typeof module)
      module.exports = e();
    else if ("function" == typeof define && false)
      define([], e);
    else {
      var f;
      "undefined" != typeof window ? f = window : "undefined" != typeof global ? f = global : "undefined" != typeof self && (f = self), f.CANNON = e();
    }
  }(function() {
    var define,
        module,
        exports;
    return (function e(t, n, r) {
      function s(o, u) {
        if (!n[o]) {
          if (!t[o]) {
            var a = typeof $__require == "function" && $__require;
            if (!u && a)
              return a(o, !0);
            if (i)
              return i(o, !0);
            throw new Error("Cannot find module '" + o + "'");
          }
          var f = n[o] = {exports: {}};
          t[o][0].call(f.exports, function(e) {
            var n = t[o][1][e];
            return s(n ? n : e);
          }, f, f.exports, e, t, n, r);
        }
        return n[o].exports;
      }
      var i = typeof $__require == "function" && $__require;
      for (var o = 0; o < r.length; o++)
        s(r[o]);
      return s;
    })({
      1: [function(_dereq_, module, exports) {
        module.exports = {
          "name": "cannon",
          "version": "0.6.2",
          "description": "A lightweight 3D physics engine written in JavaScript.",
          "homepage": "https://github.com/schteppe/cannon.js",
          "author": "Stefan Hedman <schteppe@gmail.com> (http://steffe.se)",
          "keywords": ["cannon.js", "cannon", "physics", "engine", "3d"],
          "main": "./build/cannon.js",
          "engines": {"node": "*"},
          "repository": {
            "type": "git",
            "url": "https://github.com/schteppe/cannon.js.git"
          },
          "bugs": {"url": "https://github.com/schteppe/cannon.js/issues"},
          "licenses": [{"type": "MIT"}],
          "devDependencies": {
            "jshint": "latest",
            "uglify-js": "latest",
            "nodeunit": "^0.9.0",
            "grunt": "~0.4.0",
            "grunt-contrib-jshint": "~0.1.1",
            "grunt-contrib-nodeunit": "^0.4.1",
            "grunt-contrib-concat": "~0.1.3",
            "grunt-contrib-uglify": "^0.5.1",
            "grunt-browserify": "^2.1.4",
            "grunt-contrib-yuidoc": "^0.5.2",
            "browserify": "*"
          },
          "dependencies": {}
        };
      }, {}],
      2: [function(_dereq_, module, exports) {
        module.exports = {
          version: _dereq_('../package.json').version,
          AABB: _dereq_('./collision/AABB'),
          ArrayCollisionMatrix: _dereq_('./collision/ArrayCollisionMatrix'),
          Body: _dereq_('./objects/Body'),
          Box: _dereq_('./shapes/Box'),
          Broadphase: _dereq_('./collision/Broadphase'),
          Constraint: _dereq_('./constraints/Constraint'),
          ContactEquation: _dereq_('./equations/ContactEquation'),
          Narrowphase: _dereq_('./world/Narrowphase'),
          ConeTwistConstraint: _dereq_('./constraints/ConeTwistConstraint'),
          ContactMaterial: _dereq_('./material/ContactMaterial'),
          ConvexPolyhedron: _dereq_('./shapes/ConvexPolyhedron'),
          Cylinder: _dereq_('./shapes/Cylinder'),
          DistanceConstraint: _dereq_('./constraints/DistanceConstraint'),
          Equation: _dereq_('./equations/Equation'),
          EventTarget: _dereq_('./utils/EventTarget'),
          FrictionEquation: _dereq_('./equations/FrictionEquation'),
          GSSolver: _dereq_('./solver/GSSolver'),
          GridBroadphase: _dereq_('./collision/GridBroadphase'),
          Heightfield: _dereq_('./shapes/Heightfield'),
          HingeConstraint: _dereq_('./constraints/HingeConstraint'),
          LockConstraint: _dereq_('./constraints/LockConstraint'),
          Mat3: _dereq_('./math/Mat3'),
          Material: _dereq_('./material/Material'),
          NaiveBroadphase: _dereq_('./collision/NaiveBroadphase'),
          ObjectCollisionMatrix: _dereq_('./collision/ObjectCollisionMatrix'),
          Pool: _dereq_('./utils/Pool'),
          Particle: _dereq_('./shapes/Particle'),
          Plane: _dereq_('./shapes/Plane'),
          PointToPointConstraint: _dereq_('./constraints/PointToPointConstraint'),
          Quaternion: _dereq_('./math/Quaternion'),
          Ray: _dereq_('./collision/Ray'),
          RaycastVehicle: _dereq_('./objects/RaycastVehicle'),
          RaycastResult: _dereq_('./collision/RaycastResult'),
          RigidVehicle: _dereq_('./objects/RigidVehicle'),
          RotationalEquation: _dereq_('./equations/RotationalEquation'),
          RotationalMotorEquation: _dereq_('./equations/RotationalMotorEquation'),
          SAPBroadphase: _dereq_('./collision/SAPBroadphase'),
          SPHSystem: _dereq_('./objects/SPHSystem'),
          Shape: _dereq_('./shapes/Shape'),
          Solver: _dereq_('./solver/Solver'),
          Sphere: _dereq_('./shapes/Sphere'),
          SplitSolver: _dereq_('./solver/SplitSolver'),
          Spring: _dereq_('./objects/Spring'),
          Trimesh: _dereq_('./shapes/Trimesh'),
          Vec3: _dereq_('./math/Vec3'),
          Vec3Pool: _dereq_('./utils/Vec3Pool'),
          World: _dereq_('./world/World')
        };
      }, {
        "../package.json": 1,
        "./collision/AABB": 3,
        "./collision/ArrayCollisionMatrix": 4,
        "./collision/Broadphase": 5,
        "./collision/GridBroadphase": 6,
        "./collision/NaiveBroadphase": 7,
        "./collision/ObjectCollisionMatrix": 8,
        "./collision/Ray": 9,
        "./collision/RaycastResult": 10,
        "./collision/SAPBroadphase": 11,
        "./constraints/ConeTwistConstraint": 12,
        "./constraints/Constraint": 13,
        "./constraints/DistanceConstraint": 14,
        "./constraints/HingeConstraint": 15,
        "./constraints/LockConstraint": 16,
        "./constraints/PointToPointConstraint": 17,
        "./equations/ContactEquation": 19,
        "./equations/Equation": 20,
        "./equations/FrictionEquation": 21,
        "./equations/RotationalEquation": 22,
        "./equations/RotationalMotorEquation": 23,
        "./material/ContactMaterial": 24,
        "./material/Material": 25,
        "./math/Mat3": 27,
        "./math/Quaternion": 28,
        "./math/Vec3": 30,
        "./objects/Body": 31,
        "./objects/RaycastVehicle": 32,
        "./objects/RigidVehicle": 33,
        "./objects/SPHSystem": 34,
        "./objects/Spring": 35,
        "./shapes/Box": 37,
        "./shapes/ConvexPolyhedron": 38,
        "./shapes/Cylinder": 39,
        "./shapes/Heightfield": 40,
        "./shapes/Particle": 41,
        "./shapes/Plane": 42,
        "./shapes/Shape": 43,
        "./shapes/Sphere": 44,
        "./shapes/Trimesh": 45,
        "./solver/GSSolver": 46,
        "./solver/Solver": 47,
        "./solver/SplitSolver": 48,
        "./utils/EventTarget": 49,
        "./utils/Pool": 51,
        "./utils/Vec3Pool": 54,
        "./world/Narrowphase": 55,
        "./world/World": 56
      }],
      3: [function(_dereq_, module, exports) {
        var Vec3 = _dereq_('../math/Vec3');
        var Utils = _dereq_('../utils/Utils');
        module.exports = AABB;
        function AABB(options) {
          options = options || {};
          this.lowerBound = new Vec3();
          if (options.lowerBound) {
            this.lowerBound.copy(options.lowerBound);
          }
          this.upperBound = new Vec3();
          if (options.upperBound) {
            this.upperBound.copy(options.upperBound);
          }
        }
        var tmp = new Vec3();
        AABB.prototype.setFromPoints = function(points, position, quaternion, skinSize) {
          var l = this.lowerBound,
              u = this.upperBound,
              q = quaternion;
          l.copy(points[0]);
          if (q) {
            q.vmult(l, l);
          }
          u.copy(l);
          for (var i = 1; i < points.length; i++) {
            var p = points[i];
            if (q) {
              q.vmult(p, tmp);
              p = tmp;
            }
            if (p.x > u.x) {
              u.x = p.x;
            }
            if (p.x < l.x) {
              l.x = p.x;
            }
            if (p.y > u.y) {
              u.y = p.y;
            }
            if (p.y < l.y) {
              l.y = p.y;
            }
            if (p.z > u.z) {
              u.z = p.z;
            }
            if (p.z < l.z) {
              l.z = p.z;
            }
          }
          if (position) {
            position.vadd(l, l);
            position.vadd(u, u);
          }
          if (skinSize) {
            l.x -= skinSize;
            l.y -= skinSize;
            l.z -= skinSize;
            u.x += skinSize;
            u.y += skinSize;
            u.z += skinSize;
          }
          return this;
        };
        AABB.prototype.copy = function(aabb) {
          this.lowerBound.copy(aabb.lowerBound);
          this.upperBound.copy(aabb.upperBound);
          return this;
        };
        AABB.prototype.clone = function() {
          return new AABB().copy(this);
        };
        AABB.prototype.extend = function(aabb) {
          var l = aabb.lowerBound.x;
          if (this.lowerBound.x > l) {
            this.lowerBound.x = l;
          }
          var u = aabb.upperBound.x;
          if (this.upperBound.x < u) {
            this.upperBound.x = u;
          }
          var l = aabb.lowerBound.y;
          if (this.lowerBound.y > l) {
            this.lowerBound.y = l;
          }
          var u = aabb.upperBound.y;
          if (this.upperBound.y < u) {
            this.upperBound.y = u;
          }
          var l = aabb.lowerBound.z;
          if (this.lowerBound.z > l) {
            this.lowerBound.z = l;
          }
          var u = aabb.upperBound.z;
          if (this.upperBound.z < u) {
            this.upperBound.z = u;
          }
        };
        AABB.prototype.overlaps = function(aabb) {
          var l1 = this.lowerBound,
              u1 = this.upperBound,
              l2 = aabb.lowerBound,
              u2 = aabb.upperBound;
          return ((l2.x <= u1.x && u1.x <= u2.x) || (l1.x <= u2.x && u2.x <= u1.x)) && ((l2.y <= u1.y && u1.y <= u2.y) || (l1.y <= u2.y && u2.y <= u1.y)) && ((l2.z <= u1.z && u1.z <= u2.z) || (l1.z <= u2.z && u2.z <= u1.z));
        };
        AABB.prototype.contains = function(aabb) {
          var l1 = this.lowerBound,
              u1 = this.upperBound,
              l2 = aabb.lowerBound,
              u2 = aabb.upperBound;
          return ((l1.x <= l2.x && u1.x >= u2.x) && (l1.y <= l2.y && u1.y >= u2.y) && (l1.z <= l2.z && u1.z >= u2.z));
        };
        AABB.prototype.getCorners = function(a, b, c, d, e, f, g, h) {
          var l = this.lowerBound,
              u = this.upperBound;
          a.copy(l);
          b.set(u.x, l.y, l.z);
          c.set(u.x, u.y, l.z);
          d.set(l.x, u.y, u.z);
          e.set(u.x, l.y, l.z);
          f.set(l.x, u.y, l.z);
          g.set(l.x, l.y, u.z);
          h.copy(u);
        };
        var transformIntoFrame_corners = [new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3()];
        AABB.prototype.toLocalFrame = function(frame, target) {
          var corners = transformIntoFrame_corners;
          var a = corners[0];
          var b = corners[1];
          var c = corners[2];
          var d = corners[3];
          var e = corners[4];
          var f = corners[5];
          var g = corners[6];
          var h = corners[7];
          this.getCorners(a, b, c, d, e, f, g, h);
          for (var i = 0; i !== 8; i++) {
            var corner = corners[i];
            frame.pointToLocal(corner, corner);
          }
          return target.setFromPoints(corners);
        };
        AABB.prototype.toWorldFrame = function(frame, target) {
          var corners = transformIntoFrame_corners;
          var a = corners[0];
          var b = corners[1];
          var c = corners[2];
          var d = corners[3];
          var e = corners[4];
          var f = corners[5];
          var g = corners[6];
          var h = corners[7];
          this.getCorners(a, b, c, d, e, f, g, h);
          for (var i = 0; i !== 8; i++) {
            var corner = corners[i];
            frame.pointToWorld(corner, corner);
          }
          return target.setFromPoints(corners);
        };
      }, {
        "../math/Vec3": 30,
        "../utils/Utils": 53
      }],
      4: [function(_dereq_, module, exports) {
        module.exports = ArrayCollisionMatrix;
        function ArrayCollisionMatrix() {
          this.matrix = [];
        }
        ArrayCollisionMatrix.prototype.get = function(i, j) {
          i = i.index;
          j = j.index;
          if (j > i) {
            var temp = j;
            j = i;
            i = temp;
          }
          return this.matrix[(i * (i + 1) >> 1) + j - 1];
        };
        ArrayCollisionMatrix.prototype.set = function(i, j, value) {
          i = i.index;
          j = j.index;
          if (j > i) {
            var temp = j;
            j = i;
            i = temp;
          }
          this.matrix[(i * (i + 1) >> 1) + j - 1] = value ? 1 : 0;
        };
        ArrayCollisionMatrix.prototype.reset = function() {
          for (var i = 0,
              l = this.matrix.length; i !== l; i++) {
            this.matrix[i] = 0;
          }
        };
        ArrayCollisionMatrix.prototype.setNumObjects = function(n) {
          this.matrix.length = n * (n - 1) >> 1;
        };
      }, {}],
      5: [function(_dereq_, module, exports) {
        var Body = _dereq_('../objects/Body');
        var Vec3 = _dereq_('../math/Vec3');
        var Quaternion = _dereq_('../math/Quaternion');
        var Shape = _dereq_('../shapes/Shape');
        var Plane = _dereq_('../shapes/Plane');
        module.exports = Broadphase;
        function Broadphase() {
          this.world = null;
          this.useBoundingBoxes = false;
          this.dirty = true;
        }
        Broadphase.prototype.collisionPairs = function(world, p1, p2) {
          throw new Error("collisionPairs not implemented for this BroadPhase class!");
        };
        var Broadphase_needBroadphaseCollision_STATIC_OR_KINEMATIC = Body.STATIC | Body.KINEMATIC;
        Broadphase.prototype.needBroadphaseCollision = function(bodyA, bodyB) {
          if ((bodyA.collisionFilterGroup & bodyB.collisionFilterMask) === 0 || (bodyB.collisionFilterGroup & bodyA.collisionFilterMask) === 0) {
            return false;
          }
          if (((bodyA.type & Broadphase_needBroadphaseCollision_STATIC_OR_KINEMATIC) !== 0 || bodyA.sleepState === Body.SLEEPING) && ((bodyB.type & Broadphase_needBroadphaseCollision_STATIC_OR_KINEMATIC) !== 0 || bodyB.sleepState === Body.SLEEPING)) {
            return false;
          }
          return true;
        };
        Broadphase.prototype.intersectionTest = function(bodyA, bodyB, pairs1, pairs2) {
          if (this.useBoundingBoxes) {
            this.doBoundingBoxBroadphase(bodyA, bodyB, pairs1, pairs2);
          } else {
            this.doBoundingSphereBroadphase(bodyA, bodyB, pairs1, pairs2);
          }
        };
        var Broadphase_collisionPairs_r = new Vec3(),
            Broadphase_collisionPairs_normal = new Vec3(),
            Broadphase_collisionPairs_quat = new Quaternion(),
            Broadphase_collisionPairs_relpos = new Vec3();
        Broadphase.prototype.doBoundingSphereBroadphase = function(bodyA, bodyB, pairs1, pairs2) {
          var r = Broadphase_collisionPairs_r;
          bodyB.position.vsub(bodyA.position, r);
          var boundingRadiusSum2 = Math.pow(bodyA.boundingRadius + bodyB.boundingRadius, 2);
          var norm2 = r.norm2();
          if (norm2 < boundingRadiusSum2) {
            pairs1.push(bodyA);
            pairs2.push(bodyB);
          }
        };
        Broadphase.prototype.doBoundingBoxBroadphase = function(bodyA, bodyB, pairs1, pairs2) {
          if (bodyA.aabbNeedsUpdate) {
            bodyA.computeAABB();
          }
          if (bodyB.aabbNeedsUpdate) {
            bodyB.computeAABB();
          }
          if (bodyA.aabb.overlaps(bodyB.aabb)) {
            pairs1.push(bodyA);
            pairs2.push(bodyB);
          }
        };
        var Broadphase_makePairsUnique_temp = {keys: []},
            Broadphase_makePairsUnique_p1 = [],
            Broadphase_makePairsUnique_p2 = [];
        Broadphase.prototype.makePairsUnique = function(pairs1, pairs2) {
          var t = Broadphase_makePairsUnique_temp,
              p1 = Broadphase_makePairsUnique_p1,
              p2 = Broadphase_makePairsUnique_p2,
              N = pairs1.length;
          for (var i = 0; i !== N; i++) {
            p1[i] = pairs1[i];
            p2[i] = pairs2[i];
          }
          pairs1.length = 0;
          pairs2.length = 0;
          for (var i = 0; i !== N; i++) {
            var id1 = p1[i].id,
                id2 = p2[i].id;
            var key = id1 < id2 ? id1 + "," + id2 : id2 + "," + id1;
            t[key] = i;
            t.keys.push(key);
          }
          for (var i = 0; i !== t.keys.length; i++) {
            var key = t.keys.pop(),
                pairIndex = t[key];
            pairs1.push(p1[pairIndex]);
            pairs2.push(p2[pairIndex]);
            delete t[key];
          }
        };
        Broadphase.prototype.setWorld = function(world) {};
        var bsc_dist = new Vec3();
        Broadphase.boundingSphereCheck = function(bodyA, bodyB) {
          var dist = bsc_dist;
          bodyA.position.vsub(bodyB.position, dist);
          return Math.pow(bodyA.shape.boundingSphereRadius + bodyB.shape.boundingSphereRadius, 2) > dist.norm2();
        };
        Broadphase.prototype.aabbQuery = function(world, aabb, result) {
          console.warn('.aabbQuery is not implemented in this Broadphase subclass.');
          return [];
        };
      }, {
        "../math/Quaternion": 28,
        "../math/Vec3": 30,
        "../objects/Body": 31,
        "../shapes/Plane": 42,
        "../shapes/Shape": 43
      }],
      6: [function(_dereq_, module, exports) {
        module.exports = GridBroadphase;
        var Broadphase = _dereq_('./Broadphase');
        var Vec3 = _dereq_('../math/Vec3');
        var Shape = _dereq_('../shapes/Shape');
        function GridBroadphase(aabbMin, aabbMax, nx, ny, nz) {
          Broadphase.apply(this);
          this.nx = nx || 10;
          this.ny = ny || 10;
          this.nz = nz || 10;
          this.aabbMin = aabbMin || new Vec3(100, 100, 100);
          this.aabbMax = aabbMax || new Vec3(-100, -100, -100);
          var nbins = this.nx * this.ny * this.nz;
          if (nbins <= 0) {
            throw "GridBroadphase: Each dimension's n must be >0";
          }
          this.bins = [];
          this.binLengths = [];
          this.bins.length = nbins;
          this.binLengths.length = nbins;
          for (var i = 0; i < nbins; i++) {
            this.bins[i] = [];
            this.binLengths[i] = 0;
          }
        }
        GridBroadphase.prototype = new Broadphase();
        GridBroadphase.prototype.constructor = GridBroadphase;
        var GridBroadphase_collisionPairs_d = new Vec3();
        var GridBroadphase_collisionPairs_binPos = new Vec3();
        GridBroadphase.prototype.collisionPairs = function(world, pairs1, pairs2) {
          var N = world.numObjects(),
              bodies = world.bodies;
          var max = this.aabbMax,
              min = this.aabbMin,
              nx = this.nx,
              ny = this.ny,
              nz = this.nz;
          var xstep = ny * nz;
          var ystep = nz;
          var zstep = 1;
          var xmax = max.x,
              ymax = max.y,
              zmax = max.z,
              xmin = min.x,
              ymin = min.y,
              zmin = min.z;
          var xmult = nx / (xmax - xmin),
              ymult = ny / (ymax - ymin),
              zmult = nz / (zmax - zmin);
          var binsizeX = (xmax - xmin) / nx,
              binsizeY = (ymax - ymin) / ny,
              binsizeZ = (zmax - zmin) / nz;
          var binRadius = Math.sqrt(binsizeX * binsizeX + binsizeY * binsizeY + binsizeZ * binsizeZ) * 0.5;
          var types = Shape.types;
          var SPHERE = types.SPHERE,
              PLANE = types.PLANE,
              BOX = types.BOX,
              COMPOUND = types.COMPOUND,
              CONVEXPOLYHEDRON = types.CONVEXPOLYHEDRON;
          var bins = this.bins,
              binLengths = this.binLengths,
              Nbins = this.bins.length;
          for (var i = 0; i !== Nbins; i++) {
            binLengths[i] = 0;
          }
          var ceil = Math.ceil;
          var min = Math.min;
          var max = Math.max;
          function addBoxToBins(x0, y0, z0, x1, y1, z1, bi) {
            var xoff0 = ((x0 - xmin) * xmult) | 0,
                yoff0 = ((y0 - ymin) * ymult) | 0,
                zoff0 = ((z0 - zmin) * zmult) | 0,
                xoff1 = ceil((x1 - xmin) * xmult),
                yoff1 = ceil((y1 - ymin) * ymult),
                zoff1 = ceil((z1 - zmin) * zmult);
            if (xoff0 < 0) {
              xoff0 = 0;
            } else if (xoff0 >= nx) {
              xoff0 = nx - 1;
            }
            if (yoff0 < 0) {
              yoff0 = 0;
            } else if (yoff0 >= ny) {
              yoff0 = ny - 1;
            }
            if (zoff0 < 0) {
              zoff0 = 0;
            } else if (zoff0 >= nz) {
              zoff0 = nz - 1;
            }
            if (xoff1 < 0) {
              xoff1 = 0;
            } else if (xoff1 >= nx) {
              xoff1 = nx - 1;
            }
            if (yoff1 < 0) {
              yoff1 = 0;
            } else if (yoff1 >= ny) {
              yoff1 = ny - 1;
            }
            if (zoff1 < 0) {
              zoff1 = 0;
            } else if (zoff1 >= nz) {
              zoff1 = nz - 1;
            }
            xoff0 *= xstep;
            yoff0 *= ystep;
            zoff0 *= zstep;
            xoff1 *= xstep;
            yoff1 *= ystep;
            zoff1 *= zstep;
            for (var xoff = xoff0; xoff <= xoff1; xoff += xstep) {
              for (var yoff = yoff0; yoff <= yoff1; yoff += ystep) {
                for (var zoff = zoff0; zoff <= zoff1; zoff += zstep) {
                  var idx = xoff + yoff + zoff;
                  bins[idx][binLengths[idx]++] = bi;
                }
              }
            }
          }
          for (var i = 0; i !== N; i++) {
            var bi = bodies[i];
            var si = bi.shape;
            switch (si.type) {
              case SPHERE:
                var x = bi.position.x,
                    y = bi.position.y,
                    z = bi.position.z;
                var r = si.radius;
                addBoxToBins(x - r, y - r, z - r, x + r, y + r, z + r, bi);
                break;
              case PLANE:
                if (si.worldNormalNeedsUpdate) {
                  si.computeWorldNormal(bi.quaternion);
                }
                var planeNormal = si.worldNormal;
                var xreset = xmin + binsizeX * 0.5 - bi.position.x,
                    yreset = ymin + binsizeY * 0.5 - bi.position.y,
                    zreset = zmin + binsizeZ * 0.5 - bi.position.z;
                var d = GridBroadphase_collisionPairs_d;
                d.set(xreset, yreset, zreset);
                for (var xi = 0,
                    xoff = 0; xi !== nx; xi++, xoff += xstep, d.y = yreset, d.x += binsizeX) {
                  for (var yi = 0,
                      yoff = 0; yi !== ny; yi++, yoff += ystep, d.z = zreset, d.y += binsizeY) {
                    for (var zi = 0,
                        zoff = 0; zi !== nz; zi++, zoff += zstep, d.z += binsizeZ) {
                      if (d.dot(planeNormal) < binRadius) {
                        var idx = xoff + yoff + zoff;
                        bins[idx][binLengths[idx]++] = bi;
                      }
                    }
                  }
                }
                break;
              default:
                if (bi.aabbNeedsUpdate) {
                  bi.computeAABB();
                }
                addBoxToBins(bi.aabb.lowerBound.x, bi.aabb.lowerBound.y, bi.aabb.lowerBound.z, bi.aabb.upperBound.x, bi.aabb.upperBound.y, bi.aabb.upperBound.z, bi);
                break;
            }
          }
          for (var i = 0; i !== Nbins; i++) {
            var binLength = binLengths[i];
            if (binLength > 1) {
              var bin = bins[i];
              for (var xi = 0; xi !== binLength; xi++) {
                var bi = bin[xi];
                for (var yi = 0; yi !== xi; yi++) {
                  var bj = bin[yi];
                  if (this.needBroadphaseCollision(bi, bj)) {
                    this.intersectionTest(bi, bj, pairs1, pairs2);
                  }
                }
              }
            }
          }
          this.makePairsUnique(pairs1, pairs2);
        };
      }, {
        "../math/Vec3": 30,
        "../shapes/Shape": 43,
        "./Broadphase": 5
      }],
      7: [function(_dereq_, module, exports) {
        module.exports = NaiveBroadphase;
        var Broadphase = _dereq_('./Broadphase');
        var AABB = _dereq_('./AABB');
        function NaiveBroadphase() {
          Broadphase.apply(this);
        }
        NaiveBroadphase.prototype = new Broadphase();
        NaiveBroadphase.prototype.constructor = NaiveBroadphase;
        NaiveBroadphase.prototype.collisionPairs = function(world, pairs1, pairs2) {
          var bodies = world.bodies,
              n = bodies.length,
              i,
              j,
              bi,
              bj;
          for (i = 0; i !== n; i++) {
            for (j = 0; j !== i; j++) {
              bi = bodies[i];
              bj = bodies[j];
              if (!this.needBroadphaseCollision(bi, bj)) {
                continue;
              }
              this.intersectionTest(bi, bj, pairs1, pairs2);
            }
          }
        };
        var tmpAABB = new AABB();
        NaiveBroadphase.prototype.aabbQuery = function(world, aabb, result) {
          result = result || [];
          for (var i = 0; i < world.bodies.length; i++) {
            var b = world.bodies[i];
            if (b.aabbNeedsUpdate) {
              b.computeAABB();
            }
            if (b.aabb.overlaps(aabb)) {
              result.push(b);
            }
          }
          return result;
        };
      }, {
        "./AABB": 3,
        "./Broadphase": 5
      }],
      8: [function(_dereq_, module, exports) {
        module.exports = ObjectCollisionMatrix;
        function ObjectCollisionMatrix() {
          this.matrix = {};
        }
        ObjectCollisionMatrix.prototype.get = function(i, j) {
          i = i.id;
          j = j.id;
          if (j > i) {
            var temp = j;
            j = i;
            i = temp;
          }
          return i + '-' + j in this.matrix;
        };
        ObjectCollisionMatrix.prototype.set = function(i, j, value) {
          i = i.id;
          j = j.id;
          if (j > i) {
            var temp = j;
            j = i;
            i = temp;
          }
          if (value) {
            this.matrix[i + '-' + j] = true;
          } else {
            delete this.matrix[i + '-' + j];
          }
        };
        ObjectCollisionMatrix.prototype.reset = function() {
          this.matrix = {};
        };
        ObjectCollisionMatrix.prototype.setNumObjects = function(n) {};
      }, {}],
      9: [function(_dereq_, module, exports) {
        module.exports = Ray;
        var Vec3 = _dereq_('../math/Vec3');
        var Quaternion = _dereq_('../math/Quaternion');
        var Transform = _dereq_('../math/Transform');
        var ConvexPolyhedron = _dereq_('../shapes/ConvexPolyhedron');
        var Box = _dereq_('../shapes/Box');
        var RaycastResult = _dereq_('../collision/RaycastResult');
        var Shape = _dereq_('../shapes/Shape');
        var AABB = _dereq_('../collision/AABB');
        function Ray(from, to) {
          this.from = from ? from.clone() : new Vec3();
          this.to = to ? to.clone() : new Vec3();
          this._direction = new Vec3();
          this.precision = 0.0001;
          this.checkCollisionResponse = true;
          this.skipBackfaces = false;
          this.collisionFilterMask = -1;
          this.collisionFilterGroup = -1;
          this.mode = Ray.ANY;
          this.result = new RaycastResult();
          this.hasHit = false;
          this.callback = function(result) {};
        }
        Ray.prototype.constructor = Ray;
        Ray.CLOSEST = 1;
        Ray.ANY = 2;
        Ray.ALL = 4;
        var tmpAABB = new AABB();
        var tmpArray = [];
        Ray.prototype.intersectWorld = function(world, options) {
          this.mode = options.mode || Ray.ANY;
          this.result = options.result || new RaycastResult();
          this.skipBackfaces = !!options.skipBackfaces;
          this.collisionFilterMask = typeof(options.collisionFilterMask) !== 'undefined' ? options.collisionFilterMask : -1;
          this.collisionFilterGroup = typeof(options.collisionFilterGroup) !== 'undefined' ? options.collisionFilterGroup : -1;
          if (options.from) {
            this.from.copy(options.from);
          }
          if (options.to) {
            this.to.copy(options.to);
          }
          this.callback = options.callback || function() {};
          this.hasHit = false;
          this.result.reset();
          this._updateDirection();
          this.getAABB(tmpAABB);
          tmpArray.length = 0;
          world.broadphase.aabbQuery(world, tmpAABB, tmpArray);
          this.intersectBodies(tmpArray);
          return this.hasHit;
        };
        var v1 = new Vec3(),
            v2 = new Vec3();
        Ray.pointInTriangle = pointInTriangle;
        function pointInTriangle(p, a, b, c) {
          c.vsub(a, v0);
          b.vsub(a, v1);
          p.vsub(a, v2);
          var dot00 = v0.dot(v0);
          var dot01 = v0.dot(v1);
          var dot02 = v0.dot(v2);
          var dot11 = v1.dot(v1);
          var dot12 = v1.dot(v2);
          var u,
              v;
          return ((u = dot11 * dot02 - dot01 * dot12) >= 0) && ((v = dot00 * dot12 - dot01 * dot02) >= 0) && (u + v < (dot00 * dot11 - dot01 * dot01));
        }
        var intersectBody_xi = new Vec3();
        var intersectBody_qi = new Quaternion();
        Ray.prototype.intersectBody = function(body, result) {
          if (result) {
            this.result = result;
            this._updateDirection();
          }
          var checkCollisionResponse = this.checkCollisionResponse;
          if (checkCollisionResponse && !body.collisionResponse) {
            return;
          }
          if ((this.collisionFilterGroup & body.collisionFilterMask) === 0 || (body.collisionFilterGroup & this.collisionFilterMask) === 0) {
            return;
          }
          var xi = intersectBody_xi;
          var qi = intersectBody_qi;
          for (var i = 0,
              N = body.shapes.length; i < N; i++) {
            var shape = body.shapes[i];
            if (checkCollisionResponse && !shape.collisionResponse) {
              continue;
            }
            body.quaternion.mult(body.shapeOrientations[i], qi);
            body.quaternion.vmult(body.shapeOffsets[i], xi);
            xi.vadd(body.position, xi);
            this.intersectShape(shape, qi, xi, body);
            if (this.result._shouldStop) {
              break;
            }
          }
        };
        Ray.prototype.intersectBodies = function(bodies, result) {
          if (result) {
            this.result = result;
            this._updateDirection();
          }
          for (var i = 0,
              l = bodies.length; !this.result._shouldStop && i < l; i++) {
            this.intersectBody(bodies[i]);
          }
        };
        Ray.prototype._updateDirection = function() {
          this.to.vsub(this.from, this._direction);
          this._direction.normalize();
        };
        Ray.prototype.intersectShape = function(shape, quat, position, body) {
          var from = this.from;
          var distance = distanceFromIntersection(from, this._direction, position);
          if (distance > shape.boundingSphereRadius) {
            return;
          }
          var intersectMethod = this[shape.type];
          if (intersectMethod) {
            intersectMethod.call(this, shape, quat, position, body);
          }
        };
        var vector = new Vec3();
        var normal = new Vec3();
        var intersectPoint = new Vec3();
        var a = new Vec3();
        var b = new Vec3();
        var c = new Vec3();
        var d = new Vec3();
        var tmpRaycastResult = new RaycastResult();
        Ray.prototype.intersectBox = function(shape, quat, position, body) {
          return this.intersectConvex(shape.convexPolyhedronRepresentation, quat, position, body);
        };
        Ray.prototype[Shape.types.BOX] = Ray.prototype.intersectBox;
        Ray.prototype.intersectPlane = function(shape, quat, position, body) {
          var from = this.from;
          var to = this.to;
          var direction = this._direction;
          var worldNormal = new Vec3(0, 0, 1);
          quat.vmult(worldNormal, worldNormal);
          var len = new Vec3();
          from.vsub(position, len);
          var planeToFrom = len.dot(worldNormal);
          to.vsub(position, len);
          var planeToTo = len.dot(worldNormal);
          if (planeToFrom * planeToTo > 0) {
            return;
          }
          if (from.distanceTo(to) < planeToFrom) {
            return;
          }
          var n_dot_dir = worldNormal.dot(direction);
          if (Math.abs(n_dot_dir) < this.precision) {
            return;
          }
          var planePointToFrom = new Vec3();
          var dir_scaled_with_t = new Vec3();
          var hitPointWorld = new Vec3();
          from.vsub(position, planePointToFrom);
          var t = -worldNormal.dot(planePointToFrom) / n_dot_dir;
          direction.scale(t, dir_scaled_with_t);
          from.vadd(dir_scaled_with_t, hitPointWorld);
          this.reportIntersection(worldNormal, hitPointWorld, shape, body, -1);
        };
        Ray.prototype[Shape.types.PLANE] = Ray.prototype.intersectPlane;
        Ray.prototype.getAABB = function(result) {
          var to = this.to;
          var from = this.from;
          result.lowerBound.x = Math.min(to.x, from.x);
          result.lowerBound.y = Math.min(to.y, from.y);
          result.lowerBound.z = Math.min(to.z, from.z);
          result.upperBound.x = Math.max(to.x, from.x);
          result.upperBound.y = Math.max(to.y, from.y);
          result.upperBound.z = Math.max(to.z, from.z);
        };
        var intersectConvexOptions = {faceList: [0]};
        Ray.prototype.intersectHeightfield = function(shape, quat, position, body) {
          var data = shape.data,
              w = shape.elementSize,
              worldPillarOffset = new Vec3();
          var localRay = new Ray(this.from, this.to);
          Transform.pointToLocalFrame(position, quat, localRay.from, localRay.from);
          Transform.pointToLocalFrame(position, quat, localRay.to, localRay.to);
          var index = [];
          var iMinX = null;
          var iMinY = null;
          var iMaxX = null;
          var iMaxY = null;
          var inside = shape.getIndexOfPosition(localRay.from.x, localRay.from.y, index, false);
          if (inside) {
            iMinX = index[0];
            iMinY = index[1];
            iMaxX = index[0];
            iMaxY = index[1];
          }
          inside = shape.getIndexOfPosition(localRay.to.x, localRay.to.y, index, false);
          if (inside) {
            if (iMinX === null || index[0] < iMinX) {
              iMinX = index[0];
            }
            if (iMaxX === null || index[0] > iMaxX) {
              iMaxX = index[0];
            }
            if (iMinY === null || index[1] < iMinY) {
              iMinY = index[1];
            }
            if (iMaxY === null || index[1] > iMaxY) {
              iMaxY = index[1];
            }
          }
          if (iMinX === null) {
            return;
          }
          var minMax = [];
          shape.getRectMinMax(iMinX, iMinY, iMaxX, iMaxY, minMax);
          var min = minMax[0];
          var max = minMax[1];
          for (var i = iMinX; i <= iMaxX; i++) {
            for (var j = iMinY; j <= iMaxY; j++) {
              if (this.result._shouldStop) {
                return;
              }
              shape.getConvexTrianglePillar(i, j, false);
              Transform.pointToWorldFrame(position, quat, shape.pillarOffset, worldPillarOffset);
              this.intersectConvex(shape.pillarConvex, quat, worldPillarOffset, body, intersectConvexOptions);
              if (this.result._shouldStop) {
                return;
              }
              shape.getConvexTrianglePillar(i, j, true);
              Transform.pointToWorldFrame(position, quat, shape.pillarOffset, worldPillarOffset);
              this.intersectConvex(shape.pillarConvex, quat, worldPillarOffset, body, intersectConvexOptions);
            }
          }
        };
        Ray.prototype[Shape.types.HEIGHTFIELD] = Ray.prototype.intersectHeightfield;
        var Ray_intersectSphere_intersectionPoint = new Vec3();
        var Ray_intersectSphere_normal = new Vec3();
        Ray.prototype.intersectSphere = function(shape, quat, position, body) {
          var from = this.from,
              to = this.to,
              r = shape.radius;
          var a = Math.pow(to.x - from.x, 2) + Math.pow(to.y - from.y, 2) + Math.pow(to.z - from.z, 2);
          var b = 2 * ((to.x - from.x) * (from.x - position.x) + (to.y - from.y) * (from.y - position.y) + (to.z - from.z) * (from.z - position.z));
          var c = Math.pow(from.x - position.x, 2) + Math.pow(from.y - position.y, 2) + Math.pow(from.z - position.z, 2) - Math.pow(r, 2);
          var delta = Math.pow(b, 2) - 4 * a * c;
          var intersectionPoint = Ray_intersectSphere_intersectionPoint;
          var normal = Ray_intersectSphere_normal;
          if (delta < 0) {
            return;
          } else if (delta === 0) {
            from.lerp(to, delta, intersectionPoint);
            intersectionPoint.vsub(position, normal);
            normal.normalize();
            this.reportIntersection(normal, intersectionPoint, shape, body, -1);
          } else {
            var d1 = (-b - Math.sqrt(delta)) / (2 * a);
            var d2 = (-b + Math.sqrt(delta)) / (2 * a);
            if (d1 >= 0 && d1 <= 1) {
              from.lerp(to, d1, intersectionPoint);
              intersectionPoint.vsub(position, normal);
              normal.normalize();
              this.reportIntersection(normal, intersectionPoint, shape, body, -1);
            }
            if (this.result._shouldStop) {
              return;
            }
            if (d2 >= 0 && d2 <= 1) {
              from.lerp(to, d2, intersectionPoint);
              intersectionPoint.vsub(position, normal);
              normal.normalize();
              this.reportIntersection(normal, intersectionPoint, shape, body, -1);
            }
          }
        };
        Ray.prototype[Shape.types.SPHERE] = Ray.prototype.intersectSphere;
        var intersectConvex_normal = new Vec3();
        var intersectConvex_minDistNormal = new Vec3();
        var intersectConvex_minDistIntersect = new Vec3();
        var intersectConvex_vector = new Vec3();
        Ray.prototype.intersectConvex = function intersectConvex(shape, quat, position, body, options) {
          var minDistNormal = intersectConvex_minDistNormal;
          var normal = intersectConvex_normal;
          var vector = intersectConvex_vector;
          var minDistIntersect = intersectConvex_minDistIntersect;
          var faceList = (options && options.faceList) || null;
          var faces = shape.faces,
              vertices = shape.vertices,
              normals = shape.faceNormals;
          var direction = this._direction;
          var from = this.from;
          var to = this.to;
          var fromToDistance = from.distanceTo(to);
          var minDist = -1;
          var Nfaces = faceList ? faceList.length : faces.length;
          var result = this.result;
          for (var j = 0; !result._shouldStop && j < Nfaces; j++) {
            var fi = faceList ? faceList[j] : j;
            var face = faces[fi];
            var faceNormal = normals[fi];
            var q = quat;
            var x = position;
            vector.copy(vertices[face[0]]);
            q.vmult(vector, vector);
            vector.vadd(x, vector);
            vector.vsub(from, vector);
            q.vmult(faceNormal, normal);
            var dot = direction.dot(normal);
            if (Math.abs(dot) < this.precision) {
              continue;
            }
            var scalar = normal.dot(vector) / dot;
            if (scalar < 0) {
              continue;
            }
            direction.mult(scalar, intersectPoint);
            intersectPoint.vadd(from, intersectPoint);
            a.copy(vertices[face[0]]);
            q.vmult(a, a);
            x.vadd(a, a);
            for (var i = 1; !result._shouldStop && i < face.length - 1; i++) {
              b.copy(vertices[face[i]]);
              c.copy(vertices[face[i + 1]]);
              q.vmult(b, b);
              q.vmult(c, c);
              x.vadd(b, b);
              x.vadd(c, c);
              var distance = intersectPoint.distanceTo(from);
              if (!(pointInTriangle(intersectPoint, a, b, c) || pointInTriangle(intersectPoint, b, a, c)) || distance > fromToDistance) {
                continue;
              }
              this.reportIntersection(normal, intersectPoint, shape, body, fi);
            }
          }
        };
        Ray.prototype[Shape.types.CONVEXPOLYHEDRON] = Ray.prototype.intersectConvex;
        var intersectTrimesh_normal = new Vec3();
        var intersectTrimesh_localDirection = new Vec3();
        var intersectTrimesh_localFrom = new Vec3();
        var intersectTrimesh_localTo = new Vec3();
        var intersectTrimesh_worldNormal = new Vec3();
        var intersectTrimesh_worldIntersectPoint = new Vec3();
        var intersectTrimesh_localAABB = new AABB();
        var intersectTrimesh_triangles = [];
        var intersectTrimesh_treeTransform = new Transform();
        Ray.prototype.intersectTrimesh = function intersectTrimesh(mesh, quat, position, body, options) {
          var normal = intersectTrimesh_normal;
          var triangles = intersectTrimesh_triangles;
          var treeTransform = intersectTrimesh_treeTransform;
          var minDistNormal = intersectConvex_minDistNormal;
          var vector = intersectConvex_vector;
          var minDistIntersect = intersectConvex_minDistIntersect;
          var localAABB = intersectTrimesh_localAABB;
          var localDirection = intersectTrimesh_localDirection;
          var localFrom = intersectTrimesh_localFrom;
          var localTo = intersectTrimesh_localTo;
          var worldIntersectPoint = intersectTrimesh_worldIntersectPoint;
          var worldNormal = intersectTrimesh_worldNormal;
          var faceList = (options && options.faceList) || null;
          var indices = mesh.indices,
              vertices = mesh.vertices,
              normals = mesh.faceNormals;
          var from = this.from;
          var to = this.to;
          var direction = this._direction;
          var minDist = -1;
          treeTransform.position.copy(position);
          treeTransform.quaternion.copy(quat);
          Transform.vectorToLocalFrame(position, quat, direction, localDirection);
          Transform.pointToLocalFrame(position, quat, from, localFrom);
          Transform.pointToLocalFrame(position, quat, to, localTo);
          var fromToDistanceSquared = localFrom.distanceSquared(localTo);
          mesh.tree.rayQuery(this, treeTransform, triangles);
          for (var i = 0,
              N = triangles.length; !this.result._shouldStop && i !== N; i++) {
            var trianglesIndex = triangles[i];
            mesh.getNormal(trianglesIndex, normal);
            mesh.getVertex(indices[trianglesIndex * 3], a);
            a.vsub(localFrom, vector);
            var dot = localDirection.dot(normal);
            var scalar = normal.dot(vector) / dot;
            if (scalar < 0) {
              continue;
            }
            localDirection.scale(scalar, intersectPoint);
            intersectPoint.vadd(localFrom, intersectPoint);
            mesh.getVertex(indices[trianglesIndex * 3 + 1], b);
            mesh.getVertex(indices[trianglesIndex * 3 + 2], c);
            var squaredDistance = intersectPoint.distanceSquared(localFrom);
            if (!(pointInTriangle(intersectPoint, b, a, c) || pointInTriangle(intersectPoint, a, b, c)) || squaredDistance > fromToDistanceSquared) {
              continue;
            }
            Transform.vectorToWorldFrame(quat, normal, worldNormal);
            Transform.pointToWorldFrame(position, quat, intersectPoint, worldIntersectPoint);
            this.reportIntersection(worldNormal, worldIntersectPoint, mesh, body, trianglesIndex);
          }
          triangles.length = 0;
        };
        Ray.prototype[Shape.types.TRIMESH] = Ray.prototype.intersectTrimesh;
        Ray.prototype.reportIntersection = function(normal, hitPointWorld, shape, body, hitFaceIndex) {
          var from = this.from;
          var to = this.to;
          var distance = from.distanceTo(hitPointWorld);
          var result = this.result;
          if (this.skipBackfaces && normal.dot(this._direction) > 0) {
            return;
          }
          result.hitFaceIndex = typeof(hitFaceIndex) !== 'undefined' ? hitFaceIndex : -1;
          switch (this.mode) {
            case Ray.ALL:
              this.hasHit = true;
              result.set(from, to, normal, hitPointWorld, shape, body, distance);
              result.hasHit = true;
              this.callback(result);
              break;
            case Ray.CLOSEST:
              if (distance < result.distance || !result.hasHit) {
                this.hasHit = true;
                result.hasHit = true;
                result.set(from, to, normal, hitPointWorld, shape, body, distance);
              }
              break;
            case Ray.ANY:
              this.hasHit = true;
              result.hasHit = true;
              result.set(from, to, normal, hitPointWorld, shape, body, distance);
              result._shouldStop = true;
              break;
          }
        };
        var v0 = new Vec3(),
            intersect = new Vec3();
        function distanceFromIntersection(from, direction, position) {
          position.vsub(from, v0);
          var dot = v0.dot(direction);
          direction.mult(dot, intersect);
          intersect.vadd(from, intersect);
          var distance = position.distanceTo(intersect);
          return distance;
        }
      }, {
        "../collision/AABB": 3,
        "../collision/RaycastResult": 10,
        "../math/Quaternion": 28,
        "../math/Transform": 29,
        "../math/Vec3": 30,
        "../shapes/Box": 37,
        "../shapes/ConvexPolyhedron": 38,
        "../shapes/Shape": 43
      }],
      10: [function(_dereq_, module, exports) {
        var Vec3 = _dereq_('../math/Vec3');
        module.exports = RaycastResult;
        function RaycastResult() {
          this.rayFromWorld = new Vec3();
          this.rayToWorld = new Vec3();
          this.hitNormalWorld = new Vec3();
          this.hitPointWorld = new Vec3();
          this.hasHit = false;
          this.shape = null;
          this.body = null;
          this.hitFaceIndex = -1;
          this.distance = -1;
          this._shouldStop = false;
        }
        RaycastResult.prototype.reset = function() {
          this.rayFromWorld.setZero();
          this.rayToWorld.setZero();
          this.hitNormalWorld.setZero();
          this.hitPointWorld.setZero();
          this.hasHit = false;
          this.shape = null;
          this.body = null;
          this.hitFaceIndex = -1;
          this.distance = -1;
          this._shouldStop = false;
        };
        RaycastResult.prototype.abort = function() {
          this._shouldStop = true;
        };
        RaycastResult.prototype.set = function(rayFromWorld, rayToWorld, hitNormalWorld, hitPointWorld, shape, body, distance) {
          this.rayFromWorld.copy(rayFromWorld);
          this.rayToWorld.copy(rayToWorld);
          this.hitNormalWorld.copy(hitNormalWorld);
          this.hitPointWorld.copy(hitPointWorld);
          this.shape = shape;
          this.body = body;
          this.distance = distance;
        };
      }, {"../math/Vec3": 30}],
      11: [function(_dereq_, module, exports) {
        var Shape = _dereq_('../shapes/Shape');
        var Broadphase = _dereq_('../collision/Broadphase');
        module.exports = SAPBroadphase;
        function SAPBroadphase(world) {
          Broadphase.apply(this);
          this.axisList = [];
          this.world = null;
          this.axisIndex = 0;
          var axisList = this.axisList;
          this._addBodyHandler = function(e) {
            axisList.push(e.body);
          };
          this._removeBodyHandler = function(e) {
            var idx = axisList.indexOf(e.body);
            if (idx !== -1) {
              axisList.splice(idx, 1);
            }
          };
          if (world) {
            this.setWorld(world);
          }
        }
        SAPBroadphase.prototype = new Broadphase();
        SAPBroadphase.prototype.setWorld = function(world) {
          this.axisList.length = 0;
          for (var i = 0; i < world.bodies.length; i++) {
            this.axisList.push(world.bodies[i]);
          }
          world.removeEventListener("addBody", this._addBodyHandler);
          world.removeEventListener("removeBody", this._removeBodyHandler);
          world.addEventListener("addBody", this._addBodyHandler);
          world.addEventListener("removeBody", this._removeBodyHandler);
          this.world = world;
          this.dirty = true;
        };
        SAPBroadphase.insertionSortX = function(a) {
          for (var i = 1,
              l = a.length; i < l; i++) {
            var v = a[i];
            for (var j = i - 1; j >= 0; j--) {
              if (a[j].aabb.lowerBound.x <= v.aabb.lowerBound.x) {
                break;
              }
              a[j + 1] = a[j];
            }
            a[j + 1] = v;
          }
          return a;
        };
        SAPBroadphase.insertionSortY = function(a) {
          for (var i = 1,
              l = a.length; i < l; i++) {
            var v = a[i];
            for (var j = i - 1; j >= 0; j--) {
              if (a[j].aabb.lowerBound.y <= v.aabb.lowerBound.y) {
                break;
              }
              a[j + 1] = a[j];
            }
            a[j + 1] = v;
          }
          return a;
        };
        SAPBroadphase.insertionSortZ = function(a) {
          for (var i = 1,
              l = a.length; i < l; i++) {
            var v = a[i];
            for (var j = i - 1; j >= 0; j--) {
              if (a[j].aabb.lowerBound.z <= v.aabb.lowerBound.z) {
                break;
              }
              a[j + 1] = a[j];
            }
            a[j + 1] = v;
          }
          return a;
        };
        SAPBroadphase.prototype.collisionPairs = function(world, p1, p2) {
          var bodies = this.axisList,
              N = bodies.length,
              axisIndex = this.axisIndex,
              i,
              j;
          if (this.dirty) {
            this.sortList();
            this.dirty = false;
          }
          for (i = 0; i !== N; i++) {
            var bi = bodies[i];
            for (j = i + 1; j < N; j++) {
              var bj = bodies[j];
              if (!this.needBroadphaseCollision(bi, bj)) {
                continue;
              }
              if (!SAPBroadphase.checkBounds(bi, bj, axisIndex)) {
                break;
              }
              this.intersectionTest(bi, bj, p1, p2);
            }
          }
        };
        SAPBroadphase.prototype.sortList = function() {
          var axisList = this.axisList;
          var axisIndex = this.axisIndex;
          var N = axisList.length;
          for (var i = 0; i !== N; i++) {
            var bi = axisList[i];
            if (bi.aabbNeedsUpdate) {
              bi.computeAABB();
            }
          }
          if (axisIndex === 0) {
            SAPBroadphase.insertionSortX(axisList);
          } else if (axisIndex === 1) {
            SAPBroadphase.insertionSortY(axisList);
          } else if (axisIndex === 2) {
            SAPBroadphase.insertionSortZ(axisList);
          }
        };
        SAPBroadphase.checkBounds = function(bi, bj, axisIndex) {
          var biPos;
          var bjPos;
          if (axisIndex === 0) {
            biPos = bi.position.x;
            bjPos = bj.position.x;
          } else if (axisIndex === 1) {
            biPos = bi.position.y;
            bjPos = bj.position.y;
          } else if (axisIndex === 2) {
            biPos = bi.position.z;
            bjPos = bj.position.z;
          }
          var ri = bi.boundingRadius,
              rj = bj.boundingRadius,
              boundA1 = biPos - ri,
              boundA2 = biPos + ri,
              boundB1 = bjPos - rj,
              boundB2 = bjPos + rj;
          return boundB1 < boundA2;
        };
        SAPBroadphase.prototype.autoDetectAxis = function() {
          var sumX = 0,
              sumX2 = 0,
              sumY = 0,
              sumY2 = 0,
              sumZ = 0,
              sumZ2 = 0,
              bodies = this.axisList,
              N = bodies.length,
              invN = 1 / N;
          for (var i = 0; i !== N; i++) {
            var b = bodies[i];
            var centerX = b.position.x;
            sumX += centerX;
            sumX2 += centerX * centerX;
            var centerY = b.position.y;
            sumY += centerY;
            sumY2 += centerY * centerY;
            var centerZ = b.position.z;
            sumZ += centerZ;
            sumZ2 += centerZ * centerZ;
          }
          var varianceX = sumX2 - sumX * sumX * invN,
              varianceY = sumY2 - sumY * sumY * invN,
              varianceZ = sumZ2 - sumZ * sumZ * invN;
          if (varianceX > varianceY) {
            if (varianceX > varianceZ) {
              this.axisIndex = 0;
            } else {
              this.axisIndex = 2;
            }
          } else if (varianceY > varianceZ) {
            this.axisIndex = 1;
          } else {
            this.axisIndex = 2;
          }
        };
        SAPBroadphase.prototype.aabbQuery = function(world, aabb, result) {
          result = result || [];
          if (this.dirty) {
            this.sortList();
            this.dirty = false;
          }
          var axisIndex = this.axisIndex,
              axis = 'x';
          if (axisIndex === 1) {
            axis = 'y';
          }
          if (axisIndex === 2) {
            axis = 'z';
          }
          var axisList = this.axisList;
          var lower = aabb.lowerBound[axis];
          var upper = aabb.upperBound[axis];
          for (var i = 0; i < axisList.length; i++) {
            var b = axisList[i];
            if (b.aabbNeedsUpdate) {
              b.computeAABB();
            }
            if (b.aabb.overlaps(aabb)) {
              result.push(b);
            }
          }
          return result;
        };
      }, {
        "../collision/Broadphase": 5,
        "../shapes/Shape": 43
      }],
      12: [function(_dereq_, module, exports) {
        module.exports = ConeTwistConstraint;
        var Constraint = _dereq_('./Constraint');
        var PointToPointConstraint = _dereq_('./PointToPointConstraint');
        var ConeEquation = _dereq_('../equations/ConeEquation');
        var RotationalEquation = _dereq_('../equations/RotationalEquation');
        var ContactEquation = _dereq_('../equations/ContactEquation');
        var Vec3 = _dereq_('../math/Vec3');
        function ConeTwistConstraint(bodyA, bodyB, options) {
          options = options || {};
          var maxForce = typeof(options.maxForce) !== 'undefined' ? options.maxForce : 1e6;
          var pivotA = options.pivotA ? options.pivotA.clone() : new Vec3();
          var pivotB = options.pivotB ? options.pivotB.clone() : new Vec3();
          this.axisA = options.axisA ? options.axisA.clone() : new Vec3();
          this.axisB = options.axisB ? options.axisB.clone() : new Vec3();
          PointToPointConstraint.call(this, bodyA, pivotA, bodyB, pivotB, maxForce);
          this.collideConnected = !!options.collideConnected;
          this.angle = typeof(options.angle) !== 'undefined' ? options.angle : 0;
          var c = this.coneEquation = new ConeEquation(bodyA, bodyB, options);
          var t = this.twistEquation = new RotationalEquation(bodyA, bodyB, options);
          this.twistAngle = typeof(options.twistAngle) !== 'undefined' ? options.twistAngle : 0;
          c.maxForce = 0;
          c.minForce = -maxForce;
          t.maxForce = 0;
          t.minForce = -maxForce;
          this.equations.push(c, t);
        }
        ConeTwistConstraint.prototype = new PointToPointConstraint();
        ConeTwistConstraint.constructor = ConeTwistConstraint;
        var ConeTwistConstraint_update_tmpVec1 = new Vec3();
        var ConeTwistConstraint_update_tmpVec2 = new Vec3();
        ConeTwistConstraint.prototype.update = function() {
          var bodyA = this.bodyA,
              bodyB = this.bodyB,
              cone = this.coneEquation,
              twist = this.twistEquation;
          PointToPointConstraint.prototype.update.call(this);
          bodyA.vectorToWorldFrame(this.axisA, cone.axisA);
          bodyB.vectorToWorldFrame(this.axisB, cone.axisB);
          this.axisA.tangents(twist.axisA, twist.axisA);
          bodyA.vectorToWorldFrame(twist.axisA, twist.axisA);
          this.axisB.tangents(twist.axisB, twist.axisB);
          bodyB.vectorToWorldFrame(twist.axisB, twist.axisB);
          cone.angle = this.angle;
          twist.maxAngle = this.twistAngle;
        };
      }, {
        "../equations/ConeEquation": 18,
        "../equations/ContactEquation": 19,
        "../equations/RotationalEquation": 22,
        "../math/Vec3": 30,
        "./Constraint": 13,
        "./PointToPointConstraint": 17
      }],
      13: [function(_dereq_, module, exports) {
        module.exports = Constraint;
        var Utils = _dereq_('../utils/Utils');
        function Constraint(bodyA, bodyB, options) {
          options = Utils.defaults(options, {
            collideConnected: true,
            wakeUpBodies: true
          });
          this.equations = [];
          this.bodyA = bodyA;
          this.bodyB = bodyB;
          this.id = Constraint.idCounter++;
          this.collideConnected = options.collideConnected;
          if (options.wakeUpBodies) {
            if (bodyA) {
              bodyA.wakeUp();
            }
            if (bodyB) {
              bodyB.wakeUp();
            }
          }
        }
        Constraint.prototype.update = function() {
          throw new Error("method update() not implmemented in this Constraint subclass!");
        };
        Constraint.prototype.enable = function() {
          var eqs = this.equations;
          for (var i = 0; i < eqs.length; i++) {
            eqs[i].enabled = true;
          }
        };
        Constraint.prototype.disable = function() {
          var eqs = this.equations;
          for (var i = 0; i < eqs.length; i++) {
            eqs[i].enabled = false;
          }
        };
        Constraint.idCounter = 0;
      }, {"../utils/Utils": 53}],
      14: [function(_dereq_, module, exports) {
        module.exports = DistanceConstraint;
        var Constraint = _dereq_('./Constraint');
        var ContactEquation = _dereq_('../equations/ContactEquation');
        function DistanceConstraint(bodyA, bodyB, distance, maxForce) {
          Constraint.call(this, bodyA, bodyB);
          if (typeof(distance) === "undefined") {
            distance = bodyA.position.distanceTo(bodyB.position);
          }
          if (typeof(maxForce) === "undefined") {
            maxForce = 1e6;
          }
          this.distance = distance;
          var eq = this.distanceEquation = new ContactEquation(bodyA, bodyB);
          this.equations.push(eq);
          eq.minForce = -maxForce;
          eq.maxForce = maxForce;
        }
        DistanceConstraint.prototype = new Constraint();
        DistanceConstraint.prototype.update = function() {
          var bodyA = this.bodyA;
          var bodyB = this.bodyB;
          var eq = this.distanceEquation;
          var halfDist = this.distance * 0.5;
          var normal = eq.ni;
          bodyB.position.vsub(bodyA.position, normal);
          normal.normalize();
          normal.mult(halfDist, eq.ri);
          normal.mult(-halfDist, eq.rj);
        };
      }, {
        "../equations/ContactEquation": 19,
        "./Constraint": 13
      }],
      15: [function(_dereq_, module, exports) {
        module.exports = HingeConstraint;
        var Constraint = _dereq_('./Constraint');
        var PointToPointConstraint = _dereq_('./PointToPointConstraint');
        var RotationalEquation = _dereq_('../equations/RotationalEquation');
        var RotationalMotorEquation = _dereq_('../equations/RotationalMotorEquation');
        var ContactEquation = _dereq_('../equations/ContactEquation');
        var Vec3 = _dereq_('../math/Vec3');
        function HingeConstraint(bodyA, bodyB, options) {
          options = options || {};
          var maxForce = typeof(options.maxForce) !== 'undefined' ? options.maxForce : 1e6;
          var pivotA = options.pivotA ? options.pivotA.clone() : new Vec3();
          var pivotB = options.pivotB ? options.pivotB.clone() : new Vec3();
          PointToPointConstraint.call(this, bodyA, pivotA, bodyB, pivotB, maxForce);
          var axisA = this.axisA = options.axisA ? options.axisA.clone() : new Vec3(1, 0, 0);
          axisA.normalize();
          var axisB = this.axisB = options.axisB ? options.axisB.clone() : new Vec3(1, 0, 0);
          axisB.normalize();
          var r1 = this.rotationalEquation1 = new RotationalEquation(bodyA, bodyB, options);
          var r2 = this.rotationalEquation2 = new RotationalEquation(bodyA, bodyB, options);
          var motor = this.motorEquation = new RotationalMotorEquation(bodyA, bodyB, maxForce);
          motor.enabled = false;
          this.equations.push(r1, r2, motor);
        }
        HingeConstraint.prototype = new PointToPointConstraint();
        HingeConstraint.constructor = HingeConstraint;
        HingeConstraint.prototype.enableMotor = function() {
          this.motorEquation.enabled = true;
        };
        HingeConstraint.prototype.disableMotor = function() {
          this.motorEquation.enabled = false;
        };
        HingeConstraint.prototype.setMotorSpeed = function(speed) {
          this.motorEquation.targetVelocity = speed;
        };
        HingeConstraint.prototype.setMotorMaxForce = function(maxForce) {
          this.motorEquation.maxForce = maxForce;
          this.motorEquation.minForce = -maxForce;
        };
        var HingeConstraint_update_tmpVec1 = new Vec3();
        var HingeConstraint_update_tmpVec2 = new Vec3();
        HingeConstraint.prototype.update = function() {
          var bodyA = this.bodyA,
              bodyB = this.bodyB,
              motor = this.motorEquation,
              r1 = this.rotationalEquation1,
              r2 = this.rotationalEquation2,
              worldAxisA = HingeConstraint_update_tmpVec1,
              worldAxisB = HingeConstraint_update_tmpVec2;
          var axisA = this.axisA;
          var axisB = this.axisB;
          PointToPointConstraint.prototype.update.call(this);
          bodyA.quaternion.vmult(axisA, worldAxisA);
          bodyB.quaternion.vmult(axisB, worldAxisB);
          worldAxisA.tangents(r1.axisA, r2.axisA);
          r1.axisB.copy(worldAxisB);
          r2.axisB.copy(worldAxisB);
          if (this.motorEquation.enabled) {
            bodyA.quaternion.vmult(this.axisA, motor.axisA);
            bodyB.quaternion.vmult(this.axisB, motor.axisB);
          }
        };
      }, {
        "../equations/ContactEquation": 19,
        "../equations/RotationalEquation": 22,
        "../equations/RotationalMotorEquation": 23,
        "../math/Vec3": 30,
        "./Constraint": 13,
        "./PointToPointConstraint": 17
      }],
      16: [function(_dereq_, module, exports) {
        module.exports = LockConstraint;
        var Constraint = _dereq_('./Constraint');
        var PointToPointConstraint = _dereq_('./PointToPointConstraint');
        var RotationalEquation = _dereq_('../equations/RotationalEquation');
        var RotationalMotorEquation = _dereq_('../equations/RotationalMotorEquation');
        var ContactEquation = _dereq_('../equations/ContactEquation');
        var Vec3 = _dereq_('../math/Vec3');
        function LockConstraint(bodyA, bodyB, options) {
          options = options || {};
          var maxForce = typeof(options.maxForce) !== 'undefined' ? options.maxForce : 1e6;
          var pivotA = new Vec3();
          var pivotB = new Vec3();
          var halfWay = new Vec3();
          bodyA.position.vadd(bodyB.position, halfWay);
          halfWay.scale(0.5, halfWay);
          bodyB.pointToLocalFrame(halfWay, pivotB);
          bodyA.pointToLocalFrame(halfWay, pivotA);
          PointToPointConstraint.call(this, bodyA, pivotA, bodyB, pivotB, maxForce);
          var r1 = this.rotationalEquation1 = new RotationalEquation(bodyA, bodyB, options);
          var r2 = this.rotationalEquation2 = new RotationalEquation(bodyA, bodyB, options);
          var r3 = this.rotationalEquation3 = new RotationalEquation(bodyA, bodyB, options);
          this.equations.push(r1, r2, r3);
        }
        LockConstraint.prototype = new PointToPointConstraint();
        LockConstraint.constructor = LockConstraint;
        var LockConstraint_update_tmpVec1 = new Vec3();
        var LockConstraint_update_tmpVec2 = new Vec3();
        LockConstraint.prototype.update = function() {
          var bodyA = this.bodyA,
              bodyB = this.bodyB,
              motor = this.motorEquation,
              r1 = this.rotationalEquation1,
              r2 = this.rotationalEquation2,
              r3 = this.rotationalEquation3,
              worldAxisA = LockConstraint_update_tmpVec1,
              worldAxisB = LockConstraint_update_tmpVec2;
          PointToPointConstraint.prototype.update.call(this);
          bodyA.vectorToWorldFrame(Vec3.UNIT_X, r1.axisA);
          bodyB.vectorToWorldFrame(Vec3.UNIT_Y, r1.axisB);
          bodyA.vectorToWorldFrame(Vec3.UNIT_Y, r2.axisA);
          bodyB.vectorToWorldFrame(Vec3.UNIT_Z, r2.axisB);
          bodyA.vectorToWorldFrame(Vec3.UNIT_Z, r3.axisA);
          bodyB.vectorToWorldFrame(Vec3.UNIT_X, r3.axisB);
        };
      }, {
        "../equations/ContactEquation": 19,
        "../equations/RotationalEquation": 22,
        "../equations/RotationalMotorEquation": 23,
        "../math/Vec3": 30,
        "./Constraint": 13,
        "./PointToPointConstraint": 17
      }],
      17: [function(_dereq_, module, exports) {
        module.exports = PointToPointConstraint;
        var Constraint = _dereq_('./Constraint');
        var ContactEquation = _dereq_('../equations/ContactEquation');
        var Vec3 = _dereq_('../math/Vec3');
        function PointToPointConstraint(bodyA, pivotA, bodyB, pivotB, maxForce) {
          Constraint.call(this, bodyA, bodyB);
          maxForce = typeof(maxForce) !== 'undefined' ? maxForce : 1e6;
          this.pivotA = pivotA ? pivotA.clone() : new Vec3();
          this.pivotB = pivotB ? pivotB.clone() : new Vec3();
          var x = this.equationX = new ContactEquation(bodyA, bodyB);
          var y = this.equationY = new ContactEquation(bodyA, bodyB);
          var z = this.equationZ = new ContactEquation(bodyA, bodyB);
          this.equations.push(x, y, z);
          x.minForce = y.minForce = z.minForce = -maxForce;
          x.maxForce = y.maxForce = z.maxForce = maxForce;
          x.ni.set(1, 0, 0);
          y.ni.set(0, 1, 0);
          z.ni.set(0, 0, 1);
        }
        PointToPointConstraint.prototype = new Constraint();
        PointToPointConstraint.prototype.update = function() {
          var bodyA = this.bodyA;
          var bodyB = this.bodyB;
          var x = this.equationX;
          var y = this.equationY;
          var z = this.equationZ;
          bodyA.quaternion.vmult(this.pivotA, x.ri);
          bodyB.quaternion.vmult(this.pivotB, x.rj);
          y.ri.copy(x.ri);
          y.rj.copy(x.rj);
          z.ri.copy(x.ri);
          z.rj.copy(x.rj);
        };
      }, {
        "../equations/ContactEquation": 19,
        "../math/Vec3": 30,
        "./Constraint": 13
      }],
      18: [function(_dereq_, module, exports) {
        module.exports = ConeEquation;
        var Vec3 = _dereq_('../math/Vec3');
        var Mat3 = _dereq_('../math/Mat3');
        var Equation = _dereq_('./Equation');
        function ConeEquation(bodyA, bodyB, options) {
          options = options || {};
          var maxForce = typeof(options.maxForce) !== 'undefined' ? options.maxForce : 1e6;
          Equation.call(this, bodyA, bodyB, -maxForce, maxForce);
          this.axisA = options.axisA ? options.axisA.clone() : new Vec3(1, 0, 0);
          this.axisB = options.axisB ? options.axisB.clone() : new Vec3(0, 1, 0);
          this.angle = typeof(options.angle) !== 'undefined' ? options.angle : 0;
        }
        ConeEquation.prototype = new Equation();
        ConeEquation.prototype.constructor = ConeEquation;
        var tmpVec1 = new Vec3();
        var tmpVec2 = new Vec3();
        ConeEquation.prototype.computeB = function(h) {
          var a = this.a,
              b = this.b,
              ni = this.axisA,
              nj = this.axisB,
              nixnj = tmpVec1,
              njxni = tmpVec2,
              GA = this.jacobianElementA,
              GB = this.jacobianElementB;
          ni.cross(nj, nixnj);
          nj.cross(ni, njxni);
          GA.rotational.copy(njxni);
          GB.rotational.copy(nixnj);
          var g = Math.cos(this.angle) - ni.dot(nj),
              GW = this.computeGW(),
              GiMf = this.computeGiMf();
          var B = -g * a - GW * b - h * GiMf;
          return B;
        };
      }, {
        "../math/Mat3": 27,
        "../math/Vec3": 30,
        "./Equation": 20
      }],
      19: [function(_dereq_, module, exports) {
        module.exports = ContactEquation;
        var Equation = _dereq_('./Equation');
        var Vec3 = _dereq_('../math/Vec3');
        var Mat3 = _dereq_('../math/Mat3');
        function ContactEquation(bodyA, bodyB, maxForce) {
          maxForce = typeof(maxForce) !== 'undefined' ? maxForce : 1e6;
          Equation.call(this, bodyA, bodyB, 0, maxForce);
          this.restitution = 0.0;
          this.ri = new Vec3();
          this.rj = new Vec3();
          this.ni = new Vec3();
        }
        ContactEquation.prototype = new Equation();
        ContactEquation.prototype.constructor = ContactEquation;
        var ContactEquation_computeB_temp1 = new Vec3();
        var ContactEquation_computeB_temp2 = new Vec3();
        var ContactEquation_computeB_temp3 = new Vec3();
        ContactEquation.prototype.computeB = function(h) {
          var a = this.a,
              b = this.b,
              bi = this.bi,
              bj = this.bj,
              ri = this.ri,
              rj = this.rj,
              rixn = ContactEquation_computeB_temp1,
              rjxn = ContactEquation_computeB_temp2,
              vi = bi.velocity,
              wi = bi.angularVelocity,
              fi = bi.force,
              taui = bi.torque,
              vj = bj.velocity,
              wj = bj.angularVelocity,
              fj = bj.force,
              tauj = bj.torque,
              penetrationVec = ContactEquation_computeB_temp3,
              GA = this.jacobianElementA,
              GB = this.jacobianElementB,
              n = this.ni;
          ri.cross(n, rixn);
          rj.cross(n, rjxn);
          n.negate(GA.spatial);
          rixn.negate(GA.rotational);
          GB.spatial.copy(n);
          GB.rotational.copy(rjxn);
          penetrationVec.copy(bj.position);
          penetrationVec.vadd(rj, penetrationVec);
          penetrationVec.vsub(bi.position, penetrationVec);
          penetrationVec.vsub(ri, penetrationVec);
          var g = n.dot(penetrationVec);
          var ePlusOne = this.restitution + 1;
          var GW = ePlusOne * vj.dot(n) - ePlusOne * vi.dot(n) + wj.dot(rjxn) - wi.dot(rixn);
          var GiMf = this.computeGiMf();
          var B = -g * a - GW * b - h * GiMf;
          return B;
        };
        var ContactEquation_getImpactVelocityAlongNormal_vi = new Vec3();
        var ContactEquation_getImpactVelocityAlongNormal_vj = new Vec3();
        var ContactEquation_getImpactVelocityAlongNormal_xi = new Vec3();
        var ContactEquation_getImpactVelocityAlongNormal_xj = new Vec3();
        var ContactEquation_getImpactVelocityAlongNormal_relVel = new Vec3();
        ContactEquation.prototype.getImpactVelocityAlongNormal = function() {
          var vi = ContactEquation_getImpactVelocityAlongNormal_vi;
          var vj = ContactEquation_getImpactVelocityAlongNormal_vj;
          var xi = ContactEquation_getImpactVelocityAlongNormal_xi;
          var xj = ContactEquation_getImpactVelocityAlongNormal_xj;
          var relVel = ContactEquation_getImpactVelocityAlongNormal_relVel;
          this.bi.position.vadd(this.ri, xi);
          this.bj.position.vadd(this.rj, xj);
          this.bi.getVelocityAtWorldPoint(xi, vi);
          this.bj.getVelocityAtWorldPoint(xj, vj);
          vi.vsub(vj, relVel);
          return this.ni.dot(relVel);
        };
      }, {
        "../math/Mat3": 27,
        "../math/Vec3": 30,
        "./Equation": 20
      }],
      20: [function(_dereq_, module, exports) {
        module.exports = Equation;
        var JacobianElement = _dereq_('../math/JacobianElement'),
            Vec3 = _dereq_('../math/Vec3');
        function Equation(bi, bj, minForce, maxForce) {
          this.id = Equation.id++;
          this.minForce = typeof(minForce) === "undefined" ? -1e6 : minForce;
          this.maxForce = typeof(maxForce) === "undefined" ? 1e6 : maxForce;
          this.bi = bi;
          this.bj = bj;
          this.a = 0.0;
          this.b = 0.0;
          this.eps = 0.0;
          this.jacobianElementA = new JacobianElement();
          this.jacobianElementB = new JacobianElement();
          this.enabled = true;
          this.setSpookParams(1e7, 4, 1 / 60);
        }
        Equation.prototype.constructor = Equation;
        Equation.id = 0;
        Equation.prototype.setSpookParams = function(stiffness, relaxation, timeStep) {
          var d = relaxation,
              k = stiffness,
              h = timeStep;
          this.a = 4.0 / (h * (1 + 4 * d));
          this.b = (4.0 * d) / (1 + 4 * d);
          this.eps = 4.0 / (h * h * k * (1 + 4 * d));
        };
        Equation.prototype.computeB = function(a, b, h) {
          var GW = this.computeGW(),
              Gq = this.computeGq(),
              GiMf = this.computeGiMf();
          return -Gq * a - GW * b - GiMf * h;
        };
        Equation.prototype.computeGq = function() {
          var GA = this.jacobianElementA,
              GB = this.jacobianElementB,
              bi = this.bi,
              bj = this.bj,
              xi = bi.position,
              xj = bj.position;
          return GA.spatial.dot(xi) + GB.spatial.dot(xj);
        };
        var zero = new Vec3();
        Equation.prototype.computeGW = function() {
          var GA = this.jacobianElementA,
              GB = this.jacobianElementB,
              bi = this.bi,
              bj = this.bj,
              vi = bi.velocity,
              vj = bj.velocity,
              wi = bi.angularVelocity || zero,
              wj = bj.angularVelocity || zero;
          return GA.multiplyVectors(vi, wi) + GB.multiplyVectors(vj, wj);
        };
        Equation.prototype.computeGWlambda = function() {
          var GA = this.jacobianElementA,
              GB = this.jacobianElementB,
              bi = this.bi,
              bj = this.bj,
              vi = bi.vlambda,
              vj = bj.vlambda,
              wi = bi.wlambda || zero,
              wj = bj.wlambda || zero;
          return GA.multiplyVectors(vi, wi) + GB.multiplyVectors(vj, wj);
        };
        var iMfi = new Vec3(),
            iMfj = new Vec3(),
            invIi_vmult_taui = new Vec3(),
            invIj_vmult_tauj = new Vec3();
        Equation.prototype.computeGiMf = function() {
          var GA = this.jacobianElementA,
              GB = this.jacobianElementB,
              bi = this.bi,
              bj = this.bj,
              fi = bi.force,
              ti = bi.torque,
              fj = bj.force,
              tj = bj.torque,
              invMassi = bi.invMassSolve,
              invMassj = bj.invMassSolve;
          if (bi.invInertiaWorldSolve) {
            bi.invInertiaWorldSolve.vmult(ti, invIi_vmult_taui);
          } else {
            invIi_vmult_taui.set(0, 0, 0);
          }
          if (bj.invInertiaWorldSolve) {
            bj.invInertiaWorldSolve.vmult(tj, invIj_vmult_tauj);
          } else {
            invIj_vmult_tauj.set(0, 0, 0);
          }
          fi.mult(invMassi, iMfi);
          fj.mult(invMassj, iMfj);
          return GA.multiplyVectors(iMfi, invIi_vmult_taui) + GB.multiplyVectors(iMfj, invIj_vmult_tauj);
        };
        var tmp = new Vec3();
        Equation.prototype.computeGiMGt = function() {
          var GA = this.jacobianElementA,
              GB = this.jacobianElementB,
              bi = this.bi,
              bj = this.bj,
              invMassi = bi.invMassSolve,
              invMassj = bj.invMassSolve,
              invIi = bi.invInertiaWorldSolve,
              invIj = bj.invInertiaWorldSolve,
              result = invMassi + invMassj;
          if (invIi) {
            invIi.vmult(GA.rotational, tmp);
            result += tmp.dot(GA.rotational);
          }
          if (invIj) {
            invIj.vmult(GB.rotational, tmp);
            result += tmp.dot(GB.rotational);
          }
          return result;
        };
        var addToWlambda_temp = new Vec3(),
            addToWlambda_Gi = new Vec3(),
            addToWlambda_Gj = new Vec3(),
            addToWlambda_ri = new Vec3(),
            addToWlambda_rj = new Vec3(),
            addToWlambda_Mdiag = new Vec3();
        Equation.prototype.addToWlambda = function(deltalambda) {
          var GA = this.jacobianElementA,
              GB = this.jacobianElementB,
              bi = this.bi,
              bj = this.bj,
              temp = addToWlambda_temp;
          GA.spatial.mult(bi.invMassSolve * deltalambda, temp);
          bi.vlambda.vadd(temp, bi.vlambda);
          GB.spatial.mult(bj.invMassSolve * deltalambda, temp);
          bj.vlambda.vadd(temp, bj.vlambda);
          if (bi.invInertiaWorldSolve) {
            bi.invInertiaWorldSolve.vmult(GA.rotational, temp);
            temp.mult(deltalambda, temp);
            bi.wlambda.vadd(temp, bi.wlambda);
          }
          if (bj.invInertiaWorldSolve) {
            bj.invInertiaWorldSolve.vmult(GB.rotational, temp);
            temp.mult(deltalambda, temp);
            bj.wlambda.vadd(temp, bj.wlambda);
          }
        };
        Equation.prototype.computeC = function() {
          return this.computeGiMGt() + this.eps;
        };
      }, {
        "../math/JacobianElement": 26,
        "../math/Vec3": 30
      }],
      21: [function(_dereq_, module, exports) {
        module.exports = FrictionEquation;
        var Equation = _dereq_('./Equation');
        var Vec3 = _dereq_('../math/Vec3');
        var Mat3 = _dereq_('../math/Mat3');
        function FrictionEquation(bodyA, bodyB, slipForce) {
          Equation.call(this, bodyA, bodyB, -slipForce, slipForce);
          this.ri = new Vec3();
          this.rj = new Vec3();
          this.t = new Vec3();
        }
        FrictionEquation.prototype = new Equation();
        FrictionEquation.prototype.constructor = FrictionEquation;
        var FrictionEquation_computeB_temp1 = new Vec3();
        var FrictionEquation_computeB_temp2 = new Vec3();
        FrictionEquation.prototype.computeB = function(h) {
          var a = this.a,
              b = this.b,
              bi = this.bi,
              bj = this.bj,
              ri = this.ri,
              rj = this.rj,
              rixt = FrictionEquation_computeB_temp1,
              rjxt = FrictionEquation_computeB_temp2,
              t = this.t;
          ri.cross(t, rixt);
          rj.cross(t, rjxt);
          var GA = this.jacobianElementA,
              GB = this.jacobianElementB;
          t.negate(GA.spatial);
          rixt.negate(GA.rotational);
          GB.spatial.copy(t);
          GB.rotational.copy(rjxt);
          var GW = this.computeGW();
          var GiMf = this.computeGiMf();
          var B = -GW * b - h * GiMf;
          return B;
        };
      }, {
        "../math/Mat3": 27,
        "../math/Vec3": 30,
        "./Equation": 20
      }],
      22: [function(_dereq_, module, exports) {
        module.exports = RotationalEquation;
        var Vec3 = _dereq_('../math/Vec3');
        var Mat3 = _dereq_('../math/Mat3');
        var Equation = _dereq_('./Equation');
        function RotationalEquation(bodyA, bodyB, options) {
          options = options || {};
          var maxForce = typeof(options.maxForce) !== 'undefined' ? options.maxForce : 1e6;
          Equation.call(this, bodyA, bodyB, -maxForce, maxForce);
          this.axisA = options.axisA ? options.axisA.clone() : new Vec3(1, 0, 0);
          this.axisB = options.axisB ? options.axisB.clone() : new Vec3(0, 1, 0);
          this.maxAngle = Math.PI / 2;
        }
        RotationalEquation.prototype = new Equation();
        RotationalEquation.prototype.constructor = RotationalEquation;
        var tmpVec1 = new Vec3();
        var tmpVec2 = new Vec3();
        RotationalEquation.prototype.computeB = function(h) {
          var a = this.a,
              b = this.b,
              ni = this.axisA,
              nj = this.axisB,
              nixnj = tmpVec1,
              njxni = tmpVec2,
              GA = this.jacobianElementA,
              GB = this.jacobianElementB;
          ni.cross(nj, nixnj);
          nj.cross(ni, njxni);
          GA.rotational.copy(njxni);
          GB.rotational.copy(nixnj);
          var g = Math.cos(this.maxAngle) - ni.dot(nj),
              GW = this.computeGW(),
              GiMf = this.computeGiMf();
          var B = -g * a - GW * b - h * GiMf;
          return B;
        };
      }, {
        "../math/Mat3": 27,
        "../math/Vec3": 30,
        "./Equation": 20
      }],
      23: [function(_dereq_, module, exports) {
        module.exports = RotationalMotorEquation;
        var Vec3 = _dereq_('../math/Vec3');
        var Mat3 = _dereq_('../math/Mat3');
        var Equation = _dereq_('./Equation');
        function RotationalMotorEquation(bodyA, bodyB, maxForce) {
          maxForce = typeof(maxForce) !== 'undefined' ? maxForce : 1e6;
          Equation.call(this, bodyA, bodyB, -maxForce, maxForce);
          this.axisA = new Vec3();
          this.axisB = new Vec3();
          this.targetVelocity = 0;
        }
        RotationalMotorEquation.prototype = new Equation();
        RotationalMotorEquation.prototype.constructor = RotationalMotorEquation;
        RotationalMotorEquation.prototype.computeB = function(h) {
          var a = this.a,
              b = this.b,
              bi = this.bi,
              bj = this.bj,
              axisA = this.axisA,
              axisB = this.axisB,
              GA = this.jacobianElementA,
              GB = this.jacobianElementB;
          GA.rotational.copy(axisA);
          axisB.negate(GB.rotational);
          var GW = this.computeGW() - this.targetVelocity,
              GiMf = this.computeGiMf();
          var B = -GW * b - h * GiMf;
          return B;
        };
      }, {
        "../math/Mat3": 27,
        "../math/Vec3": 30,
        "./Equation": 20
      }],
      24: [function(_dereq_, module, exports) {
        var Utils = _dereq_('../utils/Utils');
        module.exports = ContactMaterial;
        function ContactMaterial(m1, m2, options) {
          options = Utils.defaults(options, {
            friction: 0.3,
            restitution: 0.3,
            contactEquationStiffness: 1e7,
            contactEquationRelaxation: 3,
            frictionEquationStiffness: 1e7,
            frictionEquationRelaxation: 3
          });
          this.id = ContactMaterial.idCounter++;
          this.materials = [m1, m2];
          this.friction = options.friction;
          this.restitution = options.restitution;
          this.contactEquationStiffness = options.contactEquationStiffness;
          this.contactEquationRelaxation = options.contactEquationRelaxation;
          this.frictionEquationStiffness = options.frictionEquationStiffness;
          this.frictionEquationRelaxation = options.frictionEquationRelaxation;
        }
        ContactMaterial.idCounter = 0;
      }, {"../utils/Utils": 53}],
      25: [function(_dereq_, module, exports) {
        module.exports = Material;
        function Material(options) {
          var name = '';
          options = options || {};
          if (typeof(options) === 'string') {
            name = options;
            options = {};
          } else if (typeof(options) === 'object') {
            name = '';
          }
          this.name = name;
          this.id = Material.idCounter++;
          this.friction = typeof(options.friction) !== 'undefined' ? options.friction : -1;
          this.restitution = typeof(options.restitution) !== 'undefined' ? options.restitution : -1;
        }
        Material.idCounter = 0;
      }, {}],
      26: [function(_dereq_, module, exports) {
        module.exports = JacobianElement;
        var Vec3 = _dereq_('./Vec3');
        function JacobianElement() {
          this.spatial = new Vec3();
          this.rotational = new Vec3();
        }
        JacobianElement.prototype.multiplyElement = function(element) {
          return element.spatial.dot(this.spatial) + element.rotational.dot(this.rotational);
        };
        JacobianElement.prototype.multiplyVectors = function(spatial, rotational) {
          return spatial.dot(this.spatial) + rotational.dot(this.rotational);
        };
      }, {"./Vec3": 30}],
      27: [function(_dereq_, module, exports) {
        module.exports = Mat3;
        var Vec3 = _dereq_('./Vec3');
        function Mat3(elements) {
          if (elements) {
            this.elements = elements;
          } else {
            this.elements = [0, 0, 0, 0, 0, 0, 0, 0, 0];
          }
        }
        Mat3.prototype.identity = function() {
          var e = this.elements;
          e[0] = 1;
          e[1] = 0;
          e[2] = 0;
          e[3] = 0;
          e[4] = 1;
          e[5] = 0;
          e[6] = 0;
          e[7] = 0;
          e[8] = 1;
        };
        Mat3.prototype.setZero = function() {
          var e = this.elements;
          e[0] = 0;
          e[1] = 0;
          e[2] = 0;
          e[3] = 0;
          e[4] = 0;
          e[5] = 0;
          e[6] = 0;
          e[7] = 0;
          e[8] = 0;
        };
        Mat3.prototype.setTrace = function(vec3) {
          var e = this.elements;
          e[0] = vec3.x;
          e[4] = vec3.y;
          e[8] = vec3.z;
        };
        Mat3.prototype.getTrace = function(target) {
          var target = target || new Vec3();
          var e = this.elements;
          target.x = e[0];
          target.y = e[4];
          target.z = e[8];
        };
        Mat3.prototype.vmult = function(v, target) {
          target = target || new Vec3();
          var e = this.elements,
              x = v.x,
              y = v.y,
              z = v.z;
          target.x = e[0] * x + e[1] * y + e[2] * z;
          target.y = e[3] * x + e[4] * y + e[5] * z;
          target.z = e[6] * x + e[7] * y + e[8] * z;
          return target;
        };
        Mat3.prototype.smult = function(s) {
          for (var i = 0; i < this.elements.length; i++) {
            this.elements[i] *= s;
          }
        };
        Mat3.prototype.mmult = function(m, target) {
          var r = target || new Mat3();
          for (var i = 0; i < 3; i++) {
            for (var j = 0; j < 3; j++) {
              var sum = 0.0;
              for (var k = 0; k < 3; k++) {
                sum += m.elements[i + k * 3] * this.elements[k + j * 3];
              }
              r.elements[i + j * 3] = sum;
            }
          }
          return r;
        };
        Mat3.prototype.scale = function(v, target) {
          target = target || new Mat3();
          var e = this.elements,
              t = target.elements;
          for (var i = 0; i !== 3; i++) {
            t[3 * i + 0] = v.x * e[3 * i + 0];
            t[3 * i + 1] = v.y * e[3 * i + 1];
            t[3 * i + 2] = v.z * e[3 * i + 2];
          }
          return target;
        };
        Mat3.prototype.solve = function(b, target) {
          target = target || new Vec3();
          var nr = 3;
          var nc = 4;
          var eqns = [];
          for (var i = 0; i < nr * nc; i++) {
            eqns.push(0);
          }
          var i,
              j;
          for (i = 0; i < 3; i++) {
            for (j = 0; j < 3; j++) {
              eqns[i + nc * j] = this.elements[i + 3 * j];
            }
          }
          eqns[3 + 4 * 0] = b.x;
          eqns[3 + 4 * 1] = b.y;
          eqns[3 + 4 * 2] = b.z;
          var n = 3,
              k = n,
              np;
          var kp = 4;
          var p,
              els;
          do {
            i = k - n;
            if (eqns[i + nc * i] === 0) {
              for (j = i + 1; j < k; j++) {
                if (eqns[i + nc * j] !== 0) {
                  np = kp;
                  do {
                    p = kp - np;
                    eqns[p + nc * i] += eqns[p + nc * j];
                  } while (--np);
                  break;
                }
              }
            }
            if (eqns[i + nc * i] !== 0) {
              for (j = i + 1; j < k; j++) {
                var multiplier = eqns[i + nc * j] / eqns[i + nc * i];
                np = kp;
                do {
                  p = kp - np;
                  eqns[p + nc * j] = p <= i ? 0 : eqns[p + nc * j] - eqns[p + nc * i] * multiplier;
                } while (--np);
              }
            }
          } while (--n);
          target.z = eqns[2 * nc + 3] / eqns[2 * nc + 2];
          target.y = (eqns[1 * nc + 3] - eqns[1 * nc + 2] * target.z) / eqns[1 * nc + 1];
          target.x = (eqns[0 * nc + 3] - eqns[0 * nc + 2] * target.z - eqns[0 * nc + 1] * target.y) / eqns[0 * nc + 0];
          if (isNaN(target.x) || isNaN(target.y) || isNaN(target.z) || target.x === Infinity || target.y === Infinity || target.z === Infinity) {
            throw "Could not solve equation! Got x=[" + target.toString() + "], b=[" + b.toString() + "], A=[" + this.toString() + "]";
          }
          return target;
        };
        Mat3.prototype.e = function(row, column, value) {
          if (value === undefined) {
            return this.elements[column + 3 * row];
          } else {
            this.elements[column + 3 * row] = value;
          }
        };
        Mat3.prototype.copy = function(source) {
          for (var i = 0; i < source.elements.length; i++) {
            this.elements[i] = source.elements[i];
          }
          return this;
        };
        Mat3.prototype.toString = function() {
          var r = "";
          var sep = ",";
          for (var i = 0; i < 9; i++) {
            r += this.elements[i] + sep;
          }
          return r;
        };
        Mat3.prototype.reverse = function(target) {
          target = target || new Mat3();
          var nr = 3;
          var nc = 6;
          var eqns = [];
          for (var i = 0; i < nr * nc; i++) {
            eqns.push(0);
          }
          var i,
              j;
          for (i = 0; i < 3; i++) {
            for (j = 0; j < 3; j++) {
              eqns[i + nc * j] = this.elements[i + 3 * j];
            }
          }
          eqns[3 + 6 * 0] = 1;
          eqns[3 + 6 * 1] = 0;
          eqns[3 + 6 * 2] = 0;
          eqns[4 + 6 * 0] = 0;
          eqns[4 + 6 * 1] = 1;
          eqns[4 + 6 * 2] = 0;
          eqns[5 + 6 * 0] = 0;
          eqns[5 + 6 * 1] = 0;
          eqns[5 + 6 * 2] = 1;
          var n = 3,
              k = n,
              np;
          var kp = nc;
          var p;
          do {
            i = k - n;
            if (eqns[i + nc * i] === 0) {
              for (j = i + 1; j < k; j++) {
                if (eqns[i + nc * j] !== 0) {
                  np = kp;
                  do {
                    p = kp - np;
                    eqns[p + nc * i] += eqns[p + nc * j];
                  } while (--np);
                  break;
                }
              }
            }
            if (eqns[i + nc * i] !== 0) {
              for (j = i + 1; j < k; j++) {
                var multiplier = eqns[i + nc * j] / eqns[i + nc * i];
                np = kp;
                do {
                  p = kp - np;
                  eqns[p + nc * j] = p <= i ? 0 : eqns[p + nc * j] - eqns[p + nc * i] * multiplier;
                } while (--np);
              }
            }
          } while (--n);
          i = 2;
          do {
            j = i - 1;
            do {
              var multiplier = eqns[i + nc * j] / eqns[i + nc * i];
              np = nc;
              do {
                p = nc - np;
                eqns[p + nc * j] = eqns[p + nc * j] - eqns[p + nc * i] * multiplier;
              } while (--np);
            } while (j--);
          } while (--i);
          i = 2;
          do {
            var multiplier = 1 / eqns[i + nc * i];
            np = nc;
            do {
              p = nc - np;
              eqns[p + nc * i] = eqns[p + nc * i] * multiplier;
            } while (--np);
          } while (i--);
          i = 2;
          do {
            j = 2;
            do {
              p = eqns[nr + j + nc * i];
              if (isNaN(p) || p === Infinity) {
                throw "Could not reverse! A=[" + this.toString() + "]";
              }
              target.e(i, j, p);
            } while (j--);
          } while (i--);
          return target;
        };
        Mat3.prototype.setRotationFromQuaternion = function(q) {
          var x = q.x,
              y = q.y,
              z = q.z,
              w = q.w,
              x2 = x + x,
              y2 = y + y,
              z2 = z + z,
              xx = x * x2,
              xy = x * y2,
              xz = x * z2,
              yy = y * y2,
              yz = y * z2,
              zz = z * z2,
              wx = w * x2,
              wy = w * y2,
              wz = w * z2,
              e = this.elements;
          e[3 * 0 + 0] = 1 - (yy + zz);
          e[3 * 0 + 1] = xy - wz;
          e[3 * 0 + 2] = xz + wy;
          e[3 * 1 + 0] = xy + wz;
          e[3 * 1 + 1] = 1 - (xx + zz);
          e[3 * 1 + 2] = yz - wx;
          e[3 * 2 + 0] = xz - wy;
          e[3 * 2 + 1] = yz + wx;
          e[3 * 2 + 2] = 1 - (xx + yy);
          return this;
        };
        Mat3.prototype.transpose = function(target) {
          target = target || new Mat3();
          var Mt = target.elements,
              M = this.elements;
          for (var i = 0; i !== 3; i++) {
            for (var j = 0; j !== 3; j++) {
              Mt[3 * i + j] = M[3 * j + i];
            }
          }
          return target;
        };
      }, {"./Vec3": 30}],
      28: [function(_dereq_, module, exports) {
        module.exports = Quaternion;
        var Vec3 = _dereq_('./Vec3');
        function Quaternion(x, y, z, w) {
          this.x = x !== undefined ? x : 0;
          this.y = y !== undefined ? y : 0;
          this.z = z !== undefined ? z : 0;
          this.w = w !== undefined ? w : 1;
        }
        Quaternion.prototype.set = function(x, y, z, w) {
          this.x = x;
          this.y = y;
          this.z = z;
          this.w = w;
        };
        Quaternion.prototype.toString = function() {
          return this.x + "," + this.y + "," + this.z + "," + this.w;
        };
        Quaternion.prototype.toArray = function() {
          return [this.x, this.y, this.z, this.w];
        };
        Quaternion.prototype.setFromAxisAngle = function(axis, angle) {
          var s = Math.sin(angle * 0.5);
          this.x = axis.x * s;
          this.y = axis.y * s;
          this.z = axis.z * s;
          this.w = Math.cos(angle * 0.5);
        };
        Quaternion.prototype.toAxisAngle = function(targetAxis) {
          targetAxis = targetAxis || new Vec3();
          this.normalize();
          var angle = 2 * Math.acos(this.w);
          var s = Math.sqrt(1 - this.w * this.w);
          if (s < 0.001) {
            targetAxis.x = this.x;
            targetAxis.y = this.y;
            targetAxis.z = this.z;
          } else {
            targetAxis.x = this.x / s;
            targetAxis.y = this.y / s;
            targetAxis.z = this.z / s;
          }
          return [targetAxis, angle];
        };
        var sfv_t1 = new Vec3(),
            sfv_t2 = new Vec3();
        Quaternion.prototype.setFromVectors = function(u, v) {
          if (u.isAntiparallelTo(v)) {
            var t1 = sfv_t1;
            var t2 = sfv_t2;
            u.tangents(t1, t2);
            this.setFromAxisAngle(t1, Math.PI);
          } else {
            var a = u.cross(v);
            this.x = a.x;
            this.y = a.y;
            this.z = a.z;
            this.w = Math.sqrt(Math.pow(u.norm(), 2) * Math.pow(v.norm(), 2)) + u.dot(v);
            this.normalize();
          }
        };
        var Quaternion_mult_va = new Vec3();
        var Quaternion_mult_vb = new Vec3();
        var Quaternion_mult_vaxvb = new Vec3();
        Quaternion.prototype.mult = function(q, target) {
          target = target || new Quaternion();
          var w = this.w,
              va = Quaternion_mult_va,
              vb = Quaternion_mult_vb,
              vaxvb = Quaternion_mult_vaxvb;
          va.set(this.x, this.y, this.z);
          vb.set(q.x, q.y, q.z);
          target.w = w * q.w - va.dot(vb);
          va.cross(vb, vaxvb);
          target.x = w * vb.x + q.w * va.x + vaxvb.x;
          target.y = w * vb.y + q.w * va.y + vaxvb.y;
          target.z = w * vb.z + q.w * va.z + vaxvb.z;
          return target;
        };
        Quaternion.prototype.inverse = function(target) {
          var x = this.x,
              y = this.y,
              z = this.z,
              w = this.w;
          target = target || new Quaternion();
          this.conjugate(target);
          var inorm2 = 1 / (x * x + y * y + z * z + w * w);
          target.x *= inorm2;
          target.y *= inorm2;
          target.z *= inorm2;
          target.w *= inorm2;
          return target;
        };
        Quaternion.prototype.conjugate = function(target) {
          target = target || new Quaternion();
          target.x = -this.x;
          target.y = -this.y;
          target.z = -this.z;
          target.w = this.w;
          return target;
        };
        Quaternion.prototype.normalize = function() {
          var l = Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w);
          if (l === 0) {
            this.x = 0;
            this.y = 0;
            this.z = 0;
            this.w = 0;
          } else {
            l = 1 / l;
            this.x *= l;
            this.y *= l;
            this.z *= l;
            this.w *= l;
          }
        };
        Quaternion.prototype.normalizeFast = function() {
          var f = (3.0 - (this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w)) / 2.0;
          if (f === 0) {
            this.x = 0;
            this.y = 0;
            this.z = 0;
            this.w = 0;
          } else {
            this.x *= f;
            this.y *= f;
            this.z *= f;
            this.w *= f;
          }
        };
        Quaternion.prototype.vmult = function(v, target) {
          target = target || new Vec3();
          var x = v.x,
              y = v.y,
              z = v.z;
          var qx = this.x,
              qy = this.y,
              qz = this.z,
              qw = this.w;
          var ix = qw * x + qy * z - qz * y,
              iy = qw * y + qz * x - qx * z,
              iz = qw * z + qx * y - qy * x,
              iw = -qx * x - qy * y - qz * z;
          target.x = ix * qw + iw * -qx + iy * -qz - iz * -qy;
          target.y = iy * qw + iw * -qy + iz * -qx - ix * -qz;
          target.z = iz * qw + iw * -qz + ix * -qy - iy * -qx;
          return target;
        };
        Quaternion.prototype.copy = function(source) {
          this.x = source.x;
          this.y = source.y;
          this.z = source.z;
          this.w = source.w;
          return this;
        };
        Quaternion.prototype.toEuler = function(target, order) {
          order = order || "YZX";
          var heading,
              attitude,
              bank;
          var x = this.x,
              y = this.y,
              z = this.z,
              w = this.w;
          switch (order) {
            case "YZX":
              var test = x * y + z * w;
              if (test > 0.499) {
                heading = 2 * Math.atan2(x, w);
                attitude = Math.PI / 2;
                bank = 0;
              }
              if (test < -0.499) {
                heading = -2 * Math.atan2(x, w);
                attitude = -Math.PI / 2;
                bank = 0;
              }
              if (isNaN(heading)) {
                var sqx = x * x;
                var sqy = y * y;
                var sqz = z * z;
                heading = Math.atan2(2 * y * w - 2 * x * z, 1 - 2 * sqy - 2 * sqz);
                attitude = Math.asin(2 * test);
                bank = Math.atan2(2 * x * w - 2 * y * z, 1 - 2 * sqx - 2 * sqz);
              }
              break;
            default:
              throw new Error("Euler order " + order + " not supported yet.");
          }
          target.y = heading;
          target.z = attitude;
          target.x = bank;
        };
        Quaternion.prototype.setFromEuler = function(x, y, z, order) {
          order = order || "XYZ";
          var c1 = Math.cos(x / 2);
          var c2 = Math.cos(y / 2);
          var c3 = Math.cos(z / 2);
          var s1 = Math.sin(x / 2);
          var s2 = Math.sin(y / 2);
          var s3 = Math.sin(z / 2);
          if (order === 'XYZ') {
            this.x = s1 * c2 * c3 + c1 * s2 * s3;
            this.y = c1 * s2 * c3 - s1 * c2 * s3;
            this.z = c1 * c2 * s3 + s1 * s2 * c3;
            this.w = c1 * c2 * c3 - s1 * s2 * s3;
          } else if (order === 'YXZ') {
            this.x = s1 * c2 * c3 + c1 * s2 * s3;
            this.y = c1 * s2 * c3 - s1 * c2 * s3;
            this.z = c1 * c2 * s3 - s1 * s2 * c3;
            this.w = c1 * c2 * c3 + s1 * s2 * s3;
          } else if (order === 'ZXY') {
            this.x = s1 * c2 * c3 - c1 * s2 * s3;
            this.y = c1 * s2 * c3 + s1 * c2 * s3;
            this.z = c1 * c2 * s3 + s1 * s2 * c3;
            this.w = c1 * c2 * c3 - s1 * s2 * s3;
          } else if (order === 'ZYX') {
            this.x = s1 * c2 * c3 - c1 * s2 * s3;
            this.y = c1 * s2 * c3 + s1 * c2 * s3;
            this.z = c1 * c2 * s3 - s1 * s2 * c3;
            this.w = c1 * c2 * c3 + s1 * s2 * s3;
          } else if (order === 'YZX') {
            this.x = s1 * c2 * c3 + c1 * s2 * s3;
            this.y = c1 * s2 * c3 + s1 * c2 * s3;
            this.z = c1 * c2 * s3 - s1 * s2 * c3;
            this.w = c1 * c2 * c3 - s1 * s2 * s3;
          } else if (order === 'XZY') {
            this.x = s1 * c2 * c3 - c1 * s2 * s3;
            this.y = c1 * s2 * c3 - s1 * c2 * s3;
            this.z = c1 * c2 * s3 + s1 * s2 * c3;
            this.w = c1 * c2 * c3 + s1 * s2 * s3;
          }
          return this;
        };
        Quaternion.prototype.clone = function() {
          return new Quaternion(this.x, this.y, this.z, this.w);
        };
      }, {"./Vec3": 30}],
      29: [function(_dereq_, module, exports) {
        var Vec3 = _dereq_('./Vec3');
        var Quaternion = _dereq_('./Quaternion');
        module.exports = Transform;
        function Transform(options) {
          options = options || {};
          this.position = new Vec3();
          if (options.position) {
            this.position.copy(options.position);
          }
          this.quaternion = new Quaternion();
          if (options.quaternion) {
            this.quaternion.copy(options.quaternion);
          }
        }
        var tmpQuat = new Quaternion();
        Transform.pointToLocalFrame = function(position, quaternion, worldPoint, result) {
          var result = result || new Vec3();
          worldPoint.vsub(position, result);
          quaternion.conjugate(tmpQuat);
          tmpQuat.vmult(result, result);
          return result;
        };
        Transform.prototype.pointToLocal = function(worldPoint, result) {
          return Transform.pointToLocalFrame(this.position, this.quaternion, worldPoint, result);
        };
        Transform.pointToWorldFrame = function(position, quaternion, localPoint, result) {
          var result = result || new Vec3();
          quaternion.vmult(localPoint, result);
          result.vadd(position, result);
          return result;
        };
        Transform.prototype.pointToWorld = function(localPoint, result) {
          return Transform.pointToWorldFrame(this.position, this.quaternion, localPoint, result);
        };
        Transform.prototype.vectorToWorldFrame = function(localVector, result) {
          var result = result || new Vec3();
          this.quaternion.vmult(localVector, result);
          return result;
        };
        Transform.vectorToWorldFrame = function(quaternion, localVector, result) {
          quaternion.vmult(localVector, result);
          return result;
        };
        Transform.vectorToLocalFrame = function(position, quaternion, worldVector, result) {
          var result = result || new Vec3();
          quaternion.w *= -1;
          quaternion.vmult(worldVector, result);
          quaternion.w *= -1;
          return result;
        };
      }, {
        "./Quaternion": 28,
        "./Vec3": 30
      }],
      30: [function(_dereq_, module, exports) {
        module.exports = Vec3;
        var Mat3 = _dereq_('./Mat3');
        function Vec3(x, y, z) {
          this.x = x || 0.0;
          this.y = y || 0.0;
          this.z = z || 0.0;
        }
        Vec3.ZERO = new Vec3(0, 0, 0);
        Vec3.UNIT_X = new Vec3(1, 0, 0);
        Vec3.UNIT_Y = new Vec3(0, 1, 0);
        Vec3.UNIT_Z = new Vec3(0, 0, 1);
        Vec3.prototype.cross = function(v, target) {
          var vx = v.x,
              vy = v.y,
              vz = v.z,
              x = this.x,
              y = this.y,
              z = this.z;
          target = target || new Vec3();
          target.x = (y * vz) - (z * vy);
          target.y = (z * vx) - (x * vz);
          target.z = (x * vy) - (y * vx);
          return target;
        };
        Vec3.prototype.set = function(x, y, z) {
          this.x = x;
          this.y = y;
          this.z = z;
          return this;
        };
        Vec3.prototype.setZero = function() {
          this.x = this.y = this.z = 0;
        };
        Vec3.prototype.vadd = function(v, target) {
          if (target) {
            target.x = v.x + this.x;
            target.y = v.y + this.y;
            target.z = v.z + this.z;
          } else {
            return new Vec3(this.x + v.x, this.y + v.y, this.z + v.z);
          }
        };
        Vec3.prototype.vsub = function(v, target) {
          if (target) {
            target.x = this.x - v.x;
            target.y = this.y - v.y;
            target.z = this.z - v.z;
          } else {
            return new Vec3(this.x - v.x, this.y - v.y, this.z - v.z);
          }
        };
        Vec3.prototype.crossmat = function() {
          return new Mat3([0, -this.z, this.y, this.z, 0, -this.x, -this.y, this.x, 0]);
        };
        Vec3.prototype.normalize = function() {
          var x = this.x,
              y = this.y,
              z = this.z;
          var n = Math.sqrt(x * x + y * y + z * z);
          if (n > 0.0) {
            var invN = 1 / n;
            this.x *= invN;
            this.y *= invN;
            this.z *= invN;
          } else {
            this.x = 0;
            this.y = 0;
            this.z = 0;
          }
          return n;
        };
        Vec3.prototype.unit = function(target) {
          target = target || new Vec3();
          var x = this.x,
              y = this.y,
              z = this.z;
          var ninv = Math.sqrt(x * x + y * y + z * z);
          if (ninv > 0.0) {
            ninv = 1.0 / ninv;
            target.x = x * ninv;
            target.y = y * ninv;
            target.z = z * ninv;
          } else {
            target.x = 1;
            target.y = 0;
            target.z = 0;
          }
          return target;
        };
        Vec3.prototype.norm = function() {
          var x = this.x,
              y = this.y,
              z = this.z;
          return Math.sqrt(x * x + y * y + z * z);
        };
        Vec3.prototype.length = Vec3.prototype.norm;
        Vec3.prototype.norm2 = function() {
          return this.dot(this);
        };
        Vec3.prototype.lengthSquared = Vec3.prototype.norm2;
        Vec3.prototype.distanceTo = function(p) {
          var x = this.x,
              y = this.y,
              z = this.z;
          var px = p.x,
              py = p.y,
              pz = p.z;
          return Math.sqrt((px - x) * (px - x) + (py - y) * (py - y) + (pz - z) * (pz - z));
        };
        Vec3.prototype.distanceSquared = function(p) {
          var x = this.x,
              y = this.y,
              z = this.z;
          var px = p.x,
              py = p.y,
              pz = p.z;
          return (px - x) * (px - x) + (py - y) * (py - y) + (pz - z) * (pz - z);
        };
        Vec3.prototype.mult = function(scalar, target) {
          target = target || new Vec3();
          var x = this.x,
              y = this.y,
              z = this.z;
          target.x = scalar * x;
          target.y = scalar * y;
          target.z = scalar * z;
          return target;
        };
        Vec3.prototype.scale = Vec3.prototype.mult;
        Vec3.prototype.dot = function(v) {
          return this.x * v.x + this.y * v.y + this.z * v.z;
        };
        Vec3.prototype.isZero = function() {
          return this.x === 0 && this.y === 0 && this.z === 0;
        };
        Vec3.prototype.negate = function(target) {
          target = target || new Vec3();
          target.x = -this.x;
          target.y = -this.y;
          target.z = -this.z;
          return target;
        };
        var Vec3_tangents_n = new Vec3();
        var Vec3_tangents_randVec = new Vec3();
        Vec3.prototype.tangents = function(t1, t2) {
          var norm = this.norm();
          if (norm > 0.0) {
            var n = Vec3_tangents_n;
            var inorm = 1 / norm;
            n.set(this.x * inorm, this.y * inorm, this.z * inorm);
            var randVec = Vec3_tangents_randVec;
            if (Math.abs(n.x) < 0.9) {
              randVec.set(1, 0, 0);
              n.cross(randVec, t1);
            } else {
              randVec.set(0, 1, 0);
              n.cross(randVec, t1);
            }
            n.cross(t1, t2);
          } else {
            t1.set(1, 0, 0);
            t2.set(0, 1, 0);
          }
        };
        Vec3.prototype.toString = function() {
          return this.x + "," + this.y + "," + this.z;
        };
        Vec3.prototype.toArray = function() {
          return [this.x, this.y, this.z];
        };
        Vec3.prototype.copy = function(source) {
          this.x = source.x;
          this.y = source.y;
          this.z = source.z;
          return this;
        };
        Vec3.prototype.lerp = function(v, t, target) {
          var x = this.x,
              y = this.y,
              z = this.z;
          target.x = x + (v.x - x) * t;
          target.y = y + (v.y - y) * t;
          target.z = z + (v.z - z) * t;
        };
        Vec3.prototype.almostEquals = function(v, precision) {
          if (precision === undefined) {
            precision = 1e-6;
          }
          if (Math.abs(this.x - v.x) > precision || Math.abs(this.y - v.y) > precision || Math.abs(this.z - v.z) > precision) {
            return false;
          }
          return true;
        };
        Vec3.prototype.almostZero = function(precision) {
          if (precision === undefined) {
            precision = 1e-6;
          }
          if (Math.abs(this.x) > precision || Math.abs(this.y) > precision || Math.abs(this.z) > precision) {
            return false;
          }
          return true;
        };
        var antip_neg = new Vec3();
        Vec3.prototype.isAntiparallelTo = function(v, precision) {
          this.negate(antip_neg);
          return antip_neg.almostEquals(v, precision);
        };
        Vec3.prototype.clone = function() {
          return new Vec3(this.x, this.y, this.z);
        };
      }, {"./Mat3": 27}],
      31: [function(_dereq_, module, exports) {
        module.exports = Body;
        var EventTarget = _dereq_('../utils/EventTarget');
        var Shape = _dereq_('../shapes/Shape');
        var Vec3 = _dereq_('../math/Vec3');
        var Mat3 = _dereq_('../math/Mat3');
        var Quaternion = _dereq_('../math/Quaternion');
        var Material = _dereq_('../material/Material');
        var AABB = _dereq_('../collision/AABB');
        var Box = _dereq_('../shapes/Box');
        function Body(options) {
          options = options || {};
          EventTarget.apply(this);
          this.id = Body.idCounter++;
          this.world = null;
          this.preStep = null;
          this.postStep = null;
          this.vlambda = new Vec3();
          this.collisionFilterGroup = typeof(options.collisionFilterGroup) === 'number' ? options.collisionFilterGroup : 1;
          this.collisionFilterMask = typeof(options.collisionFilterMask) === 'number' ? options.collisionFilterMask : 1;
          this.collisionResponse = true;
          this.position = new Vec3();
          if (options.position) {
            this.position.copy(options.position);
          }
          this.previousPosition = new Vec3();
          this.initPosition = new Vec3();
          this.velocity = new Vec3();
          if (options.velocity) {
            this.velocity.copy(options.velocity);
          }
          this.initVelocity = new Vec3();
          this.force = new Vec3();
          var mass = typeof(options.mass) === 'number' ? options.mass : 0;
          this.mass = mass;
          this.invMass = mass > 0 ? 1.0 / mass : 0;
          this.material = options.material || null;
          this.linearDamping = typeof(options.linearDamping) === 'number' ? options.linearDamping : 0.01;
          this.type = (mass <= 0.0 ? Body.STATIC : Body.DYNAMIC);
          if (typeof(options.type) === typeof(Body.STATIC)) {
            this.type = options.type;
          }
          this.allowSleep = typeof(options.allowSleep) !== 'undefined' ? options.allowSleep : true;
          this.sleepState = 0;
          this.sleepSpeedLimit = typeof(options.sleepSpeedLimit) !== 'undefined' ? options.sleepSpeedLimit : 0.1;
          this.sleepTimeLimit = typeof(options.sleepTimeLimit) !== 'undefined' ? options.sleepTimeLimit : 1;
          this.timeLastSleepy = 0;
          this._wakeUpAfterNarrowphase = false;
          this.torque = new Vec3();
          this.quaternion = new Quaternion();
          if (options.quaternion) {
            this.quaternion.copy(options.quaternion);
          }
          this.initQuaternion = new Quaternion();
          this.angularVelocity = new Vec3();
          if (options.angularVelocity) {
            this.angularVelocity.copy(options.angularVelocity);
          }
          this.initAngularVelocity = new Vec3();
          this.interpolatedPosition = new Vec3();
          this.interpolatedQuaternion = new Quaternion();
          this.shapes = [];
          this.shapeOffsets = [];
          this.shapeOrientations = [];
          this.inertia = new Vec3();
          this.invInertia = new Vec3();
          this.invInertiaWorld = new Mat3();
          this.invMassSolve = 0;
          this.invInertiaSolve = new Vec3();
          this.invInertiaWorldSolve = new Mat3();
          this.fixedRotation = typeof(options.fixedRotation) !== "undefined" ? options.fixedRotation : false;
          this.angularDamping = typeof(options.angularDamping) !== 'undefined' ? options.angularDamping : 0.01;
          this.aabb = new AABB();
          this.aabbNeedsUpdate = true;
          this.wlambda = new Vec3();
          if (options.shape) {
            this.addShape(options.shape);
          }
          this.updateMassProperties();
        }
        Body.prototype = new EventTarget();
        Body.prototype.constructor = Body;
        Body.DYNAMIC = 1;
        Body.STATIC = 2;
        Body.KINEMATIC = 4;
        Body.AWAKE = 0;
        Body.SLEEPY = 1;
        Body.SLEEPING = 2;
        Body.idCounter = 0;
        Body.prototype.wakeUp = function() {
          var s = this.sleepState;
          this.sleepState = 0;
          if (s === Body.SLEEPING) {
            this.dispatchEvent({type: "wakeup"});
          }
        };
        Body.prototype.sleep = function() {
          this.sleepState = Body.SLEEPING;
          this.velocity.set(0, 0, 0);
          this.angularVelocity.set(0, 0, 0);
        };
        Body.sleepyEvent = {type: "sleepy"};
        Body.sleepEvent = {type: "sleep"};
        Body.prototype.sleepTick = function(time) {
          if (this.allowSleep) {
            var sleepState = this.sleepState;
            var speedSquared = this.velocity.norm2() + this.angularVelocity.norm2();
            var speedLimitSquared = Math.pow(this.sleepSpeedLimit, 2);
            if (sleepState === Body.AWAKE && speedSquared < speedLimitSquared) {
              this.sleepState = Body.SLEEPY;
              this.timeLastSleepy = time;
              this.dispatchEvent(Body.sleepyEvent);
            } else if (sleepState === Body.SLEEPY && speedSquared > speedLimitSquared) {
              this.wakeUp();
            } else if (sleepState === Body.SLEEPY && (time - this.timeLastSleepy) > this.sleepTimeLimit) {
              this.sleep();
              this.dispatchEvent(Body.sleepEvent);
            }
          }
        };
        Body.prototype.updateSolveMassProperties = function() {
          if (this.sleepState === Body.SLEEPING || this.type === Body.KINEMATIC) {
            this.invMassSolve = 0;
            this.invInertiaSolve.setZero();
            this.invInertiaWorldSolve.setZero();
          } else {
            this.invMassSolve = this.invMass;
            this.invInertiaSolve.copy(this.invInertia);
            this.invInertiaWorldSolve.copy(this.invInertiaWorld);
          }
        };
        Body.prototype.pointToLocalFrame = function(worldPoint, result) {
          var result = result || new Vec3();
          worldPoint.vsub(this.position, result);
          this.quaternion.conjugate().vmult(result, result);
          return result;
        };
        Body.prototype.vectorToLocalFrame = function(worldVector, result) {
          var result = result || new Vec3();
          this.quaternion.conjugate().vmult(worldVector, result);
          return result;
        };
        Body.prototype.pointToWorldFrame = function(localPoint, result) {
          var result = result || new Vec3();
          this.quaternion.vmult(localPoint, result);
          result.vadd(this.position, result);
          return result;
        };
        Body.prototype.vectorToWorldFrame = function(localVector, result) {
          var result = result || new Vec3();
          this.quaternion.vmult(localVector, result);
          return result;
        };
        var tmpVec = new Vec3();
        var tmpQuat = new Quaternion();
        Body.prototype.addShape = function(shape, _offset, _orientation) {
          var offset = new Vec3();
          var orientation = new Quaternion();
          if (_offset) {
            offset.copy(_offset);
          }
          if (_orientation) {
            orientation.copy(_orientation);
          }
          this.shapes.push(shape);
          this.shapeOffsets.push(offset);
          this.shapeOrientations.push(orientation);
          this.updateMassProperties();
          this.updateBoundingRadius();
          this.aabbNeedsUpdate = true;
          return this;
        };
        Body.prototype.updateBoundingRadius = function() {
          var shapes = this.shapes,
              shapeOffsets = this.shapeOffsets,
              N = shapes.length,
              radius = 0;
          for (var i = 0; i !== N; i++) {
            var shape = shapes[i];
            shape.updateBoundingSphereRadius();
            var offset = shapeOffsets[i].norm(),
                r = shape.boundingSphereRadius;
            if (offset + r > radius) {
              radius = offset + r;
            }
          }
          this.boundingRadius = radius;
        };
        var computeAABB_shapeAABB = new AABB();
        Body.prototype.computeAABB = function() {
          var shapes = this.shapes,
              shapeOffsets = this.shapeOffsets,
              shapeOrientations = this.shapeOrientations,
              N = shapes.length,
              offset = tmpVec,
              orientation = tmpQuat,
              bodyQuat = this.quaternion,
              aabb = this.aabb,
              shapeAABB = computeAABB_shapeAABB;
          for (var i = 0; i !== N; i++) {
            var shape = shapes[i];
            shapeOrientations[i].mult(bodyQuat, orientation);
            orientation.vmult(shapeOffsets[i], offset);
            offset.vadd(this.position, offset);
            shape.calculateWorldAABB(offset, orientation, shapeAABB.lowerBound, shapeAABB.upperBound);
            if (i === 0) {
              aabb.copy(shapeAABB);
            } else {
              aabb.extend(shapeAABB);
            }
          }
          this.aabbNeedsUpdate = false;
        };
        var uiw_m1 = new Mat3(),
            uiw_m2 = new Mat3(),
            uiw_m3 = new Mat3();
        Body.prototype.updateInertiaWorld = function(force) {
          var I = this.invInertia;
          if (I.x === I.y && I.y === I.z && !force) {} else {
            var m1 = uiw_m1,
                m2 = uiw_m2,
                m3 = uiw_m3;
            m1.setRotationFromQuaternion(this.quaternion);
            m1.transpose(m2);
            m1.scale(I, m1);
            m1.mmult(m2, this.invInertiaWorld);
          }
        };
        var Body_applyForce_r = new Vec3();
        var Body_applyForce_rotForce = new Vec3();
        Body.prototype.applyForce = function(force, worldPoint) {
          if (this.type !== Body.DYNAMIC) {
            return;
          }
          var r = Body_applyForce_r;
          worldPoint.vsub(this.position, r);
          var rotForce = Body_applyForce_rotForce;
          r.cross(force, rotForce);
          this.force.vadd(force, this.force);
          this.torque.vadd(rotForce, this.torque);
        };
        var Body_applyLocalForce_worldForce = new Vec3();
        var Body_applyLocalForce_worldPoint = new Vec3();
        Body.prototype.applyLocalForce = function(localForce, localPoint) {
          if (this.type !== Body.DYNAMIC) {
            return;
          }
          var worldForce = Body_applyLocalForce_worldForce;
          var worldPoint = Body_applyLocalForce_worldPoint;
          this.vectorToWorldFrame(localForce, worldForce);
          this.pointToWorldFrame(localPoint, worldPoint);
          this.applyForce(worldForce, worldPoint);
        };
        var Body_applyImpulse_r = new Vec3();
        var Body_applyImpulse_velo = new Vec3();
        var Body_applyImpulse_rotVelo = new Vec3();
        Body.prototype.applyImpulse = function(impulse, worldPoint) {
          if (this.type !== Body.DYNAMIC) {
            return;
          }
          var r = Body_applyImpulse_r;
          worldPoint.vsub(this.position, r);
          var velo = Body_applyImpulse_velo;
          velo.copy(impulse);
          velo.mult(this.invMass, velo);
          this.velocity.vadd(velo, this.velocity);
          var rotVelo = Body_applyImpulse_rotVelo;
          r.cross(impulse, rotVelo);
          this.invInertiaWorld.vmult(rotVelo, rotVelo);
          this.angularVelocity.vadd(rotVelo, this.angularVelocity);
        };
        var Body_applyLocalImpulse_worldImpulse = new Vec3();
        var Body_applyLocalImpulse_worldPoint = new Vec3();
        Body.prototype.applyLocalImpulse = function(localImpulse, localPoint) {
          if (this.type !== Body.DYNAMIC) {
            return;
          }
          var worldImpulse = Body_applyLocalImpulse_worldImpulse;
          var worldPoint = Body_applyLocalImpulse_worldPoint;
          this.vectorToWorldFrame(localImpulse, worldImpulse);
          this.pointToWorldFrame(localPoint, worldPoint);
          this.applyImpulse(worldImpulse, worldPoint);
        };
        var Body_updateMassProperties_halfExtents = new Vec3();
        Body.prototype.updateMassProperties = function() {
          var halfExtents = Body_updateMassProperties_halfExtents;
          this.invMass = this.mass > 0 ? 1.0 / this.mass : 0;
          var I = this.inertia;
          var fixed = this.fixedRotation;
          this.computeAABB();
          halfExtents.set((this.aabb.upperBound.x - this.aabb.lowerBound.x) / 2, (this.aabb.upperBound.y - this.aabb.lowerBound.y) / 2, (this.aabb.upperBound.z - this.aabb.lowerBound.z) / 2);
          Box.calculateInertia(halfExtents, this.mass, I);
          this.invInertia.set(I.x > 0 && !fixed ? 1.0 / I.x : 0, I.y > 0 && !fixed ? 1.0 / I.y : 0, I.z > 0 && !fixed ? 1.0 / I.z : 0);
          this.updateInertiaWorld(true);
        };
        Body.prototype.getVelocityAtWorldPoint = function(worldPoint, result) {
          var r = new Vec3();
          worldPoint.vsub(this.position, r);
          this.angularVelocity.cross(r, result);
          this.velocity.vadd(result, result);
          return result;
        };
      }, {
        "../collision/AABB": 3,
        "../material/Material": 25,
        "../math/Mat3": 27,
        "../math/Quaternion": 28,
        "../math/Vec3": 30,
        "../shapes/Box": 37,
        "../shapes/Shape": 43,
        "../utils/EventTarget": 49
      }],
      32: [function(_dereq_, module, exports) {
        var Body = _dereq_('./Body');
        var Vec3 = _dereq_('../math/Vec3');
        var Quaternion = _dereq_('../math/Quaternion');
        var RaycastResult = _dereq_('../collision/RaycastResult');
        var Ray = _dereq_('../collision/Ray');
        var WheelInfo = _dereq_('../objects/WheelInfo');
        module.exports = RaycastVehicle;
        function RaycastVehicle(options) {
          this.chassisBody = options.chassisBody;
          this.wheelInfos = [];
          this.sliding = false;
          this.world = null;
          this.indexRightAxis = typeof(options.indexRightAxis) !== 'undefined' ? options.indexRightAxis : 1;
          this.indexForwardAxis = typeof(options.indexForwardAxis) !== 'undefined' ? options.indexForwardAxis : 0;
          this.indexUpAxis = typeof(options.indexUpAxis) !== 'undefined' ? options.indexUpAxis : 2;
        }
        var tmpVec1 = new Vec3();
        var tmpVec2 = new Vec3();
        var tmpVec3 = new Vec3();
        var tmpVec4 = new Vec3();
        var tmpVec5 = new Vec3();
        var tmpVec6 = new Vec3();
        var tmpRay = new Ray();
        RaycastVehicle.prototype.addWheel = function(options) {
          options = options || {};
          var info = new WheelInfo(options);
          var index = this.wheelInfos.length;
          this.wheelInfos.push(info);
          return index;
        };
        RaycastVehicle.prototype.setSteeringValue = function(value, wheelIndex) {
          var wheel = this.wheelInfos[wheelIndex];
          wheel.steering = value;
        };
        var torque = new Vec3();
        RaycastVehicle.prototype.applyEngineForce = function(value, wheelIndex) {
          this.wheelInfos[wheelIndex].engineForce = value;
        };
        RaycastVehicle.prototype.setBrake = function(brake, wheelIndex) {
          this.wheelInfos[wheelIndex].brake = brake;
        };
        RaycastVehicle.prototype.addToWorld = function(world) {
          var constraints = this.constraints;
          world.add(this.chassisBody);
          var that = this;
          this.preStepCallback = function() {
            that.updateVehicle(world.dt);
          };
          world.addEventListener('preStep', this.preStepCallback);
          this.world = world;
        };
        RaycastVehicle.prototype.getVehicleAxisWorld = function(axisIndex, result) {
          result.set(axisIndex === 0 ? 1 : 0, axisIndex === 1 ? 1 : 0, axisIndex === 2 ? 1 : 0);
          this.chassisBody.vectorToWorldFrame(result, result);
        };
        RaycastVehicle.prototype.updateVehicle = function(timeStep) {
          var wheelInfos = this.wheelInfos;
          var numWheels = wheelInfos.length;
          var chassisBody = this.chassisBody;
          for (var i = 0; i < numWheels; i++) {
            this.updateWheelTransform(i);
          }
          this.currentVehicleSpeedKmHour = 3.6 * chassisBody.velocity.norm();
          var forwardWorld = new Vec3();
          this.getVehicleAxisWorld(this.indexForwardAxis, forwardWorld);
          if (forwardWorld.dot(chassisBody.velocity) < 0) {
            this.currentVehicleSpeedKmHour *= -1;
          }
          for (var i = 0; i < numWheels; i++) {
            this.castRay(wheelInfos[i]);
          }
          this.updateSuspension(timeStep);
          var impulse = new Vec3();
          var relpos = new Vec3();
          for (var i = 0; i < numWheels; i++) {
            var wheel = wheelInfos[i];
            var suspensionForce = wheel.suspensionForce;
            if (suspensionForce > wheel.maxSuspensionForce) {
              suspensionForce = wheel.maxSuspensionForce;
            }
            wheel.raycastResult.hitNormalWorld.scale(suspensionForce * timeStep, impulse);
            wheel.raycastResult.hitPointWorld.vsub(chassisBody.position, relpos);
            chassisBody.applyImpulse(impulse, wheel.raycastResult.hitPointWorld);
          }
          this.updateFriction(timeStep);
          var hitNormalWorldScaledWithProj = new Vec3();
          var fwd = new Vec3();
          var vel = new Vec3();
          for (i = 0; i < numWheels; i++) {
            var wheel = wheelInfos[i];
            chassisBody.getVelocityAtWorldPoint(wheel.chassisConnectionPointWorld, vel);
            var m = 1;
            switch (this.indexUpAxis) {
              case 1:
                m = -1;
                break;
            }
            if (wheel.isInContact) {
              this.getVehicleAxisWorld(this.indexForwardAxis, fwd);
              var proj = fwd.dot(wheel.raycastResult.hitNormalWorld);
              wheel.raycastResult.hitNormalWorld.scale(proj, hitNormalWorldScaledWithProj);
              fwd.vsub(hitNormalWorldScaledWithProj, fwd);
              var proj2 = fwd.dot(vel);
              wheel.deltaRotation = m * proj2 * timeStep / wheel.radius;
            }
            if ((wheel.sliding || !wheel.isInContact) && wheel.engineForce !== 0 && wheel.useCustomSlidingRotationalSpeed) {
              wheel.deltaRotation = (wheel.engineForce > 0 ? 1 : -1) * wheel.customSlidingRotationalSpeed * timeStep;
            }
            if (Math.abs(wheel.brake) > Math.abs(wheel.engineForce)) {
              wheel.deltaRotation = 0;
            }
            wheel.rotation += wheel.deltaRotation;
            wheel.deltaRotation *= 0.99;
          }
        };
        RaycastVehicle.prototype.updateSuspension = function(deltaTime) {
          var chassisBody = this.chassisBody;
          var chassisMass = chassisBody.mass;
          var wheelInfos = this.wheelInfos;
          var numWheels = wheelInfos.length;
          for (var w_it = 0; w_it < numWheels; w_it++) {
            var wheel = wheelInfos[w_it];
            if (wheel.isInContact) {
              var force;
              var susp_length = wheel.suspensionRestLength;
              var current_length = wheel.suspensionLength;
              var length_diff = (susp_length - current_length);
              force = wheel.suspensionStiffness * length_diff * wheel.clippedInvContactDotSuspension;
              var projected_rel_vel = wheel.suspensionRelativeVelocity;
              var susp_damping;
              if (projected_rel_vel < 0) {
                susp_damping = wheel.dampingCompression;
              } else {
                susp_damping = wheel.dampingRelaxation;
              }
              force -= susp_damping * projected_rel_vel;
              wheel.suspensionForce = force * chassisMass;
              if (wheel.suspensionForce < 0) {
                wheel.suspensionForce = 0;
              }
            } else {
              wheel.suspensionForce = 0;
            }
          }
        };
        RaycastVehicle.prototype.removeFromWorld = function(world) {
          var constraints = this.constraints;
          world.remove(this.chassisBody);
          world.removeEventListener('preStep', this.preStepCallback);
          this.world = null;
        };
        var castRay_rayvector = new Vec3();
        var castRay_target = new Vec3();
        RaycastVehicle.prototype.castRay = function(wheel) {
          var rayvector = castRay_rayvector;
          var target = castRay_target;
          this.updateWheelTransformWorld(wheel);
          var chassisBody = this.chassisBody;
          var depth = -1;
          var raylen = wheel.suspensionRestLength + wheel.radius;
          wheel.directionWorld.scale(raylen, rayvector);
          var source = wheel.chassisConnectionPointWorld;
          source.vadd(rayvector, target);
          var raycastResult = wheel.raycastResult;
          var param = 0;
          raycastResult.reset();
          var oldState = chassisBody.collisionResponse;
          chassisBody.collisionResponse = false;
          this.world.rayTest(source, target, raycastResult);
          chassisBody.collisionResponse = oldState;
          var object = raycastResult.body;
          wheel.raycastResult.groundObject = 0;
          if (object) {
            depth = raycastResult.distance;
            wheel.raycastResult.hitNormalWorld = raycastResult.hitNormalWorld;
            wheel.isInContact = true;
            var hitDistance = raycastResult.distance;
            wheel.suspensionLength = hitDistance - wheel.radius;
            var minSuspensionLength = wheel.suspensionRestLength - wheel.maxSuspensionTravel;
            var maxSuspensionLength = wheel.suspensionRestLength + wheel.maxSuspensionTravel;
            if (wheel.suspensionLength < minSuspensionLength) {
              wheel.suspensionLength = minSuspensionLength;
            }
            if (wheel.suspensionLength > maxSuspensionLength) {
              wheel.suspensionLength = maxSuspensionLength;
              wheel.raycastResult.reset();
            }
            var denominator = wheel.raycastResult.hitNormalWorld.dot(wheel.directionWorld);
            var chassis_velocity_at_contactPoint = new Vec3();
            chassisBody.getVelocityAtWorldPoint(wheel.raycastResult.hitPointWorld, chassis_velocity_at_contactPoint);
            var projVel = wheel.raycastResult.hitNormalWorld.dot(chassis_velocity_at_contactPoint);
            if (denominator >= -0.1) {
              wheel.suspensionRelativeVelocity = 0;
              wheel.clippedInvContactDotSuspension = 1 / 0.1;
            } else {
              var inv = -1 / denominator;
              wheel.suspensionRelativeVelocity = projVel * inv;
              wheel.clippedInvContactDotSuspension = inv;
            }
          } else {
            wheel.suspensionLength = wheel.suspensionRestLength + 0 * wheel.maxSuspensionTravel;
            wheel.suspensionRelativeVelocity = 0.0;
            wheel.directionWorld.scale(-1, wheel.raycastResult.hitNormalWorld);
            wheel.clippedInvContactDotSuspension = 1.0;
          }
          return depth;
        };
        RaycastVehicle.prototype.updateWheelTransformWorld = function(wheel) {
          wheel.isInContact = false;
          var chassisBody = this.chassisBody;
          chassisBody.pointToWorldFrame(wheel.chassisConnectionPointLocal, wheel.chassisConnectionPointWorld);
          chassisBody.vectorToWorldFrame(wheel.directionLocal, wheel.directionWorld);
          chassisBody.vectorToWorldFrame(wheel.axleLocal, wheel.axleWorld);
        };
        RaycastVehicle.prototype.updateWheelTransform = function(wheelIndex) {
          var up = tmpVec4;
          var right = tmpVec5;
          var fwd = tmpVec6;
          var wheel = this.wheelInfos[wheelIndex];
          this.updateWheelTransformWorld(wheel);
          wheel.directionLocal.scale(-1, up);
          right.copy(wheel.axleLocal);
          up.cross(right, fwd);
          fwd.normalize();
          right.normalize();
          var steering = wheel.steering;
          var steeringOrn = new Quaternion();
          steeringOrn.setFromAxisAngle(up, steering);
          var rotatingOrn = new Quaternion();
          rotatingOrn.setFromAxisAngle(right, wheel.rotation);
          var q = wheel.worldTransform.quaternion;
          this.chassisBody.quaternion.mult(steeringOrn, q);
          q.mult(rotatingOrn, q);
          q.normalize();
          var p = wheel.worldTransform.position;
          p.copy(wheel.directionWorld);
          p.scale(wheel.suspensionLength, p);
          p.vadd(wheel.chassisConnectionPointWorld, p);
        };
        var directions = [new Vec3(1, 0, 0), new Vec3(0, 1, 0), new Vec3(0, 0, 1)];
        RaycastVehicle.prototype.getWheelTransformWorld = function(wheelIndex) {
          return this.wheelInfos[wheelIndex].worldTransform;
        };
        var updateFriction_surfNormalWS_scaled_proj = new Vec3();
        var updateFriction_axle = [];
        var updateFriction_forwardWS = [];
        var sideFrictionStiffness2 = 1;
        RaycastVehicle.prototype.updateFriction = function(timeStep) {
          var surfNormalWS_scaled_proj = updateFriction_surfNormalWS_scaled_proj;
          var wheelInfos = this.wheelInfos;
          var numWheels = wheelInfos.length;
          var chassisBody = this.chassisBody;
          var forwardWS = updateFriction_forwardWS;
          var axle = updateFriction_axle;
          var numWheelsOnGround = 0;
          for (var i = 0; i < numWheels; i++) {
            var wheel = wheelInfos[i];
            var groundObject = wheel.raycastResult.body;
            if (groundObject) {
              numWheelsOnGround++;
            }
            wheel.sideImpulse = 0;
            wheel.forwardImpulse = 0;
            if (!forwardWS[i]) {
              forwardWS[i] = new Vec3();
            }
            if (!axle[i]) {
              axle[i] = new Vec3();
            }
          }
          for (var i = 0; i < numWheels; i++) {
            var wheel = wheelInfos[i];
            var groundObject = wheel.raycastResult.body;
            if (groundObject) {
              var axlei = axle[i];
              var wheelTrans = this.getWheelTransformWorld(i);
              wheelTrans.vectorToWorldFrame(directions[this.indexRightAxis], axlei);
              var surfNormalWS = wheel.raycastResult.hitNormalWorld;
              var proj = axlei.dot(surfNormalWS);
              surfNormalWS.scale(proj, surfNormalWS_scaled_proj);
              axlei.vsub(surfNormalWS_scaled_proj, axlei);
              axlei.normalize();
              surfNormalWS.cross(axlei, forwardWS[i]);
              forwardWS[i].normalize();
              wheel.sideImpulse = resolveSingleBilateral(chassisBody, wheel.raycastResult.hitPointWorld, groundObject, wheel.raycastResult.hitPointWorld, axlei);
              wheel.sideImpulse *= sideFrictionStiffness2;
            }
          }
          var sideFactor = 1;
          var fwdFactor = 0.5;
          this.sliding = false;
          for (var i = 0; i < numWheels; i++) {
            var wheel = wheelInfos[i];
            var groundObject = wheel.raycastResult.body;
            var rollingFriction = 0;
            wheel.slipInfo = 1;
            if (groundObject) {
              var defaultRollingFrictionImpulse = 0;
              var maxImpulse = wheel.brake ? wheel.brake : defaultRollingFrictionImpulse;
              rollingFriction = calcRollingFriction(chassisBody, groundObject, wheel.raycastResult.hitPointWorld, forwardWS[i], maxImpulse);
              rollingFriction += wheel.engineForce * timeStep;
              var factor = maxImpulse / rollingFriction;
              wheel.slipInfo *= factor;
            }
            wheel.forwardImpulse = 0;
            wheel.skidInfo = 1;
            if (groundObject) {
              wheel.skidInfo = 1;
              var maximp = wheel.suspensionForce * timeStep * wheel.frictionSlip;
              var maximpSide = maximp;
              var maximpSquared = maximp * maximpSide;
              wheel.forwardImpulse = rollingFriction;
              var x = wheel.forwardImpulse * fwdFactor;
              var y = wheel.sideImpulse * sideFactor;
              var impulseSquared = x * x + y * y;
              wheel.sliding = false;
              if (impulseSquared > maximpSquared) {
                this.sliding = true;
                wheel.sliding = true;
                var factor = maximp / Math.sqrt(impulseSquared);
                wheel.skidInfo *= factor;
              }
            }
          }
          if (this.sliding) {
            for (var i = 0; i < numWheels; i++) {
              var wheel = wheelInfos[i];
              if (wheel.sideImpulse !== 0) {
                if (wheel.skidInfo < 1) {
                  wheel.forwardImpulse *= wheel.skidInfo;
                  wheel.sideImpulse *= wheel.skidInfo;
                }
              }
            }
          }
          for (var i = 0; i < numWheels; i++) {
            var wheel = wheelInfos[i];
            var rel_pos = new Vec3();
            rel_pos.copy(wheel.raycastResult.hitPointWorld);
            if (wheel.forwardImpulse !== 0) {
              var impulse = new Vec3();
              forwardWS[i].scale(wheel.forwardImpulse, impulse);
              chassisBody.applyImpulse(impulse, rel_pos);
            }
            if (wheel.sideImpulse !== 0) {
              var groundObject = wheel.raycastResult.body;
              var rel_pos2 = new Vec3();
              rel_pos2.copy(wheel.raycastResult.hitPointWorld);
              var sideImp = new Vec3();
              axle[i].scale(wheel.sideImpulse, sideImp);
              chassisBody.pointToLocalFrame(rel_pos, rel_pos);
              rel_pos['xyz'[this.indexUpAxis]] *= wheel.rollInfluence;
              chassisBody.pointToWorldFrame(rel_pos, rel_pos);
              chassisBody.applyImpulse(sideImp, rel_pos);
              sideImp.scale(-1, sideImp);
              groundObject.applyImpulse(sideImp, rel_pos2);
            }
          }
        };
        var calcRollingFriction_vel1 = new Vec3();
        var calcRollingFriction_vel2 = new Vec3();
        var calcRollingFriction_vel = new Vec3();
        function calcRollingFriction(body0, body1, frictionPosWorld, frictionDirectionWorld, maxImpulse) {
          var j1 = 0;
          var contactPosWorld = frictionPosWorld;
          var vel1 = calcRollingFriction_vel1;
          var vel2 = calcRollingFriction_vel2;
          var vel = calcRollingFriction_vel;
          body0.getVelocityAtWorldPoint(contactPosWorld, vel1);
          body1.getVelocityAtWorldPoint(contactPosWorld, vel2);
          vel1.vsub(vel2, vel);
          var vrel = frictionDirectionWorld.dot(vel);
          var denom0 = computeImpulseDenominator(body0, frictionPosWorld, frictionDirectionWorld);
          var denom1 = computeImpulseDenominator(body1, frictionPosWorld, frictionDirectionWorld);
          var relaxation = 1;
          var jacDiagABInv = relaxation / (denom0 + denom1);
          j1 = -vrel * jacDiagABInv;
          if (maxImpulse < j1) {
            j1 = maxImpulse;
          }
          if (j1 < -maxImpulse) {
            j1 = -maxImpulse;
          }
          return j1;
        }
        var computeImpulseDenominator_r0 = new Vec3();
        var computeImpulseDenominator_c0 = new Vec3();
        var computeImpulseDenominator_vec = new Vec3();
        var computeImpulseDenominator_m = new Vec3();
        function computeImpulseDenominator(body, pos, normal) {
          var r0 = computeImpulseDenominator_r0;
          var c0 = computeImpulseDenominator_c0;
          var vec = computeImpulseDenominator_vec;
          var m = computeImpulseDenominator_m;
          pos.vsub(body.position, r0);
          r0.cross(normal, c0);
          body.invInertiaWorld.vmult(c0, m);
          m.cross(r0, vec);
          return body.invMass + normal.dot(vec);
        }
        var resolveSingleBilateral_vel1 = new Vec3();
        var resolveSingleBilateral_vel2 = new Vec3();
        var resolveSingleBilateral_vel = new Vec3();
        function resolveSingleBilateral(body1, pos1, body2, pos2, normal, impulse) {
          var normalLenSqr = normal.norm2();
          if (normalLenSqr > 1.1) {
            return 0;
          }
          var vel1 = resolveSingleBilateral_vel1;
          var vel2 = resolveSingleBilateral_vel2;
          var vel = resolveSingleBilateral_vel;
          body1.getVelocityAtWorldPoint(pos1, vel1);
          body2.getVelocityAtWorldPoint(pos2, vel2);
          vel1.vsub(vel2, vel);
          var rel_vel = normal.dot(vel);
          var contactDamping = 0.2;
          var massTerm = 1 / (body1.invMass + body2.invMass);
          var impulse = -contactDamping * rel_vel * massTerm;
          return impulse;
        }
      }, {
        "../collision/Ray": 9,
        "../collision/RaycastResult": 10,
        "../math/Quaternion": 28,
        "../math/Vec3": 30,
        "../objects/WheelInfo": 36,
        "./Body": 31
      }],
      33: [function(_dereq_, module, exports) {
        var Body = _dereq_('./Body');
        var Sphere = _dereq_('../shapes/Sphere');
        var Box = _dereq_('../shapes/Box');
        var Vec3 = _dereq_('../math/Vec3');
        var HingeConstraint = _dereq_('../constraints/HingeConstraint');
        module.exports = RigidVehicle;
        function RigidVehicle(options) {
          this.wheelBodies = [];
          this.coordinateSystem = typeof(options.coordinateSystem) === 'undefined' ? new Vec3(1, 2, 3) : options.coordinateSystem.clone();
          this.chassisBody = options.chassisBody;
          if (!this.chassisBody) {
            var chassisShape = new Box(new Vec3(5, 2, 0.5));
            this.chassisBody = new Body(1, chassisShape);
          }
          this.constraints = [];
          this.wheelAxes = [];
          this.wheelForces = [];
        }
        RigidVehicle.prototype.addWheel = function(options) {
          options = options || {};
          var wheelBody = options.body;
          if (!wheelBody) {
            wheelBody = new Body(1, new Sphere(1.2));
          }
          this.wheelBodies.push(wheelBody);
          this.wheelForces.push(0);
          var zero = new Vec3();
          var position = typeof(options.position) !== 'undefined' ? options.position.clone() : new Vec3();
          var worldPosition = new Vec3();
          this.chassisBody.pointToWorldFrame(position, worldPosition);
          wheelBody.position.set(worldPosition.x, worldPosition.y, worldPosition.z);
          var axis = typeof(options.axis) !== 'undefined' ? options.axis.clone() : new Vec3(0, 1, 0);
          this.wheelAxes.push(axis);
          var hingeConstraint = new HingeConstraint(this.chassisBody, wheelBody, {
            pivotA: position,
            axisA: axis,
            pivotB: Vec3.ZERO,
            axisB: axis,
            collideConnected: false
          });
          this.constraints.push(hingeConstraint);
          return this.wheelBodies.length - 1;
        };
        RigidVehicle.prototype.setSteeringValue = function(value, wheelIndex) {
          var axis = this.wheelAxes[wheelIndex];
          var c = Math.cos(value),
              s = Math.sin(value),
              x = axis.x,
              y = axis.y;
          this.constraints[wheelIndex].axisA.set(c * x - s * y, s * x + c * y, 0);
        };
        RigidVehicle.prototype.setMotorSpeed = function(value, wheelIndex) {
          var hingeConstraint = this.constraints[wheelIndex];
          hingeConstraint.enableMotor();
          hingeConstraint.motorTargetVelocity = value;
        };
        RigidVehicle.prototype.disableMotor = function(wheelIndex) {
          var hingeConstraint = this.constraints[wheelIndex];
          hingeConstraint.disableMotor();
        };
        var torque = new Vec3();
        RigidVehicle.prototype.setWheelForce = function(value, wheelIndex) {
          this.wheelForces[wheelIndex] = value;
        };
        RigidVehicle.prototype.applyWheelForce = function(value, wheelIndex) {
          var axis = this.wheelAxes[wheelIndex];
          var wheelBody = this.wheelBodies[wheelIndex];
          var bodyTorque = wheelBody.torque;
          axis.scale(value, torque);
          wheelBody.vectorToWorldFrame(torque, torque);
          bodyTorque.vadd(torque, bodyTorque);
        };
        RigidVehicle.prototype.addToWorld = function(world) {
          var constraints = this.constraints;
          var bodies = this.wheelBodies.concat([this.chassisBody]);
          for (var i = 0; i < bodies.length; i++) {
            world.add(bodies[i]);
          }
          for (var i = 0; i < constraints.length; i++) {
            world.addConstraint(constraints[i]);
          }
          world.addEventListener('preStep', this._update.bind(this));
        };
        RigidVehicle.prototype._update = function() {
          var wheelForces = this.wheelForces;
          for (var i = 0; i < wheelForces.length; i++) {
            this.applyWheelForce(wheelForces[i], i);
          }
        };
        RigidVehicle.prototype.removeFromWorld = function(world) {
          var constraints = this.constraints;
          var bodies = this.wheelBodies.concat([this.chassisBody]);
          for (var i = 0; i < bodies.length; i++) {
            world.remove(bodies[i]);
          }
          for (var i = 0; i < constraints.length; i++) {
            world.removeConstraint(constraints[i]);
          }
        };
        var worldAxis = new Vec3();
        RigidVehicle.prototype.getWheelSpeed = function(wheelIndex) {
          var axis = this.wheelAxes[wheelIndex];
          var wheelBody = this.wheelBodies[wheelIndex];
          var w = wheelBody.angularVelocity;
          this.chassisBody.vectorToWorldFrame(axis, worldAxis);
          return w.dot(worldAxis);
        };
      }, {
        "../constraints/HingeConstraint": 15,
        "../math/Vec3": 30,
        "../shapes/Box": 37,
        "../shapes/Sphere": 44,
        "./Body": 31
      }],
      34: [function(_dereq_, module, exports) {
        module.exports = SPHSystem;
        var Shape = _dereq_('../shapes/Shape');
        var Vec3 = _dereq_('../math/Vec3');
        var Quaternion = _dereq_('../math/Quaternion');
        var Particle = _dereq_('../shapes/Particle');
        var Body = _dereq_('../objects/Body');
        var Material = _dereq_('../material/Material');
        function SPHSystem() {
          this.particles = [];
          this.density = 1;
          this.smoothingRadius = 1;
          this.speedOfSound = 1;
          this.viscosity = 0.01;
          this.eps = 0.000001;
          this.pressures = [];
          this.densities = [];
          this.neighbors = [];
        }
        SPHSystem.prototype.add = function(particle) {
          this.particles.push(particle);
          if (this.neighbors.length < this.particles.length) {
            this.neighbors.push([]);
          }
        };
        SPHSystem.prototype.remove = function(particle) {
          var idx = this.particles.indexOf(particle);
          if (idx !== -1) {
            this.particles.splice(idx, 1);
            if (this.neighbors.length > this.particles.length) {
              this.neighbors.pop();
            }
          }
        };
        var SPHSystem_getNeighbors_dist = new Vec3();
        SPHSystem.prototype.getNeighbors = function(particle, neighbors) {
          var N = this.particles.length,
              id = particle.id,
              R2 = this.smoothingRadius * this.smoothingRadius,
              dist = SPHSystem_getNeighbors_dist;
          for (var i = 0; i !== N; i++) {
            var p = this.particles[i];
            p.position.vsub(particle.position, dist);
            if (id !== p.id && dist.norm2() < R2) {
              neighbors.push(p);
            }
          }
        };
        var SPHSystem_update_dist = new Vec3(),
            SPHSystem_update_a_pressure = new Vec3(),
            SPHSystem_update_a_visc = new Vec3(),
            SPHSystem_update_gradW = new Vec3(),
            SPHSystem_update_r_vec = new Vec3(),
            SPHSystem_update_u = new Vec3();
        SPHSystem.prototype.update = function() {
          var N = this.particles.length,
              dist = SPHSystem_update_dist,
              cs = this.speedOfSound,
              eps = this.eps;
          for (var i = 0; i !== N; i++) {
            var p = this.particles[i];
            var neighbors = this.neighbors[i];
            neighbors.length = 0;
            this.getNeighbors(p, neighbors);
            neighbors.push(this.particles[i]);
            var numNeighbors = neighbors.length;
            var sum = 0.0;
            for (var j = 0; j !== numNeighbors; j++) {
              p.position.vsub(neighbors[j].position, dist);
              var len = dist.norm();
              var weight = this.w(len);
              sum += neighbors[j].mass * weight;
            }
            this.densities[i] = sum;
            this.pressures[i] = cs * cs * (this.densities[i] - this.density);
          }
          var a_pressure = SPHSystem_update_a_pressure;
          var a_visc = SPHSystem_update_a_visc;
          var gradW = SPHSystem_update_gradW;
          var r_vec = SPHSystem_update_r_vec;
          var u = SPHSystem_update_u;
          for (var i = 0; i !== N; i++) {
            var particle = this.particles[i];
            a_pressure.set(0, 0, 0);
            a_visc.set(0, 0, 0);
            var Pij;
            var nabla;
            var Vij;
            var neighbors = this.neighbors[i];
            var numNeighbors = neighbors.length;
            for (var j = 0; j !== numNeighbors; j++) {
              var neighbor = neighbors[j];
              particle.position.vsub(neighbor.position, r_vec);
              var r = r_vec.norm();
              Pij = -neighbor.mass * (this.pressures[i] / (this.densities[i] * this.densities[i] + eps) + this.pressures[j] / (this.densities[j] * this.densities[j] + eps));
              this.gradw(r_vec, gradW);
              gradW.mult(Pij, gradW);
              a_pressure.vadd(gradW, a_pressure);
              neighbor.velocity.vsub(particle.velocity, u);
              u.mult(1.0 / (0.0001 + this.densities[i] * this.densities[j]) * this.viscosity * neighbor.mass, u);
              nabla = this.nablaw(r);
              u.mult(nabla, u);
              a_visc.vadd(u, a_visc);
            }
            a_visc.mult(particle.mass, a_visc);
            a_pressure.mult(particle.mass, a_pressure);
            particle.force.vadd(a_visc, particle.force);
            particle.force.vadd(a_pressure, particle.force);
          }
        };
        SPHSystem.prototype.w = function(r) {
          var h = this.smoothingRadius;
          return 315.0 / (64.0 * Math.PI * Math.pow(h, 9)) * Math.pow(h * h - r * r, 3);
        };
        SPHSystem.prototype.gradw = function(rVec, resultVec) {
          var r = rVec.norm(),
              h = this.smoothingRadius;
          rVec.mult(945.0 / (32.0 * Math.PI * Math.pow(h, 9)) * Math.pow((h * h - r * r), 2), resultVec);
        };
        SPHSystem.prototype.nablaw = function(r) {
          var h = this.smoothingRadius;
          var nabla = 945.0 / (32.0 * Math.PI * Math.pow(h, 9)) * (h * h - r * r) * (7 * r * r - 3 * h * h);
          return nabla;
        };
      }, {
        "../material/Material": 25,
        "../math/Quaternion": 28,
        "../math/Vec3": 30,
        "../objects/Body": 31,
        "../shapes/Particle": 41,
        "../shapes/Shape": 43
      }],
      35: [function(_dereq_, module, exports) {
        var Vec3 = _dereq_('../math/Vec3');
        module.exports = Spring;
        function Spring(bodyA, bodyB, options) {
          options = options || {};
          this.restLength = typeof(options.restLength) === "number" ? options.restLength : 1;
          this.stiffness = options.stiffness || 100;
          this.damping = options.damping || 1;
          this.bodyA = bodyA;
          this.bodyB = bodyB;
          this.localAnchorA = new Vec3();
          this.localAnchorB = new Vec3();
          if (options.localAnchorA) {
            this.localAnchorA.copy(options.localAnchorA);
          }
          if (options.localAnchorB) {
            this.localAnchorB.copy(options.localAnchorB);
          }
          if (options.worldAnchorA) {
            this.setWorldAnchorA(options.worldAnchorA);
          }
          if (options.worldAnchorB) {
            this.setWorldAnchorB(options.worldAnchorB);
          }
        }
        Spring.prototype.setWorldAnchorA = function(worldAnchorA) {
          this.bodyA.pointToLocalFrame(worldAnchorA, this.localAnchorA);
        };
        Spring.prototype.setWorldAnchorB = function(worldAnchorB) {
          this.bodyB.pointToLocalFrame(worldAnchorB, this.localAnchorB);
        };
        Spring.prototype.getWorldAnchorA = function(result) {
          this.bodyA.pointToWorldFrame(this.localAnchorA, result);
        };
        Spring.prototype.getWorldAnchorB = function(result) {
          this.bodyB.pointToWorldFrame(this.localAnchorB, result);
        };
        var applyForce_r = new Vec3(),
            applyForce_r_unit = new Vec3(),
            applyForce_u = new Vec3(),
            applyForce_f = new Vec3(),
            applyForce_worldAnchorA = new Vec3(),
            applyForce_worldAnchorB = new Vec3(),
            applyForce_ri = new Vec3(),
            applyForce_rj = new Vec3(),
            applyForce_ri_x_f = new Vec3(),
            applyForce_rj_x_f = new Vec3(),
            applyForce_tmp = new Vec3();
        Spring.prototype.applyForce = function() {
          var k = this.stiffness,
              d = this.damping,
              l = this.restLength,
              bodyA = this.bodyA,
              bodyB = this.bodyB,
              r = applyForce_r,
              r_unit = applyForce_r_unit,
              u = applyForce_u,
              f = applyForce_f,
              tmp = applyForce_tmp;
          var worldAnchorA = applyForce_worldAnchorA,
              worldAnchorB = applyForce_worldAnchorB,
              ri = applyForce_ri,
              rj = applyForce_rj,
              ri_x_f = applyForce_ri_x_f,
              rj_x_f = applyForce_rj_x_f;
          this.getWorldAnchorA(worldAnchorA);
          this.getWorldAnchorB(worldAnchorB);
          worldAnchorA.vsub(bodyA.position, ri);
          worldAnchorB.vsub(bodyB.position, rj);
          worldAnchorB.vsub(worldAnchorA, r);
          var rlen = r.norm();
          r_unit.copy(r);
          r_unit.normalize();
          bodyB.velocity.vsub(bodyA.velocity, u);
          bodyB.angularVelocity.cross(rj, tmp);
          u.vadd(tmp, u);
          bodyA.angularVelocity.cross(ri, tmp);
          u.vsub(tmp, u);
          r_unit.mult(-k * (rlen - l) - d * u.dot(r_unit), f);
          bodyA.force.vsub(f, bodyA.force);
          bodyB.force.vadd(f, bodyB.force);
          ri.cross(f, ri_x_f);
          rj.cross(f, rj_x_f);
          bodyA.torque.vsub(ri_x_f, bodyA.torque);
          bodyB.torque.vadd(rj_x_f, bodyB.torque);
        };
      }, {"../math/Vec3": 30}],
      36: [function(_dereq_, module, exports) {
        var Vec3 = _dereq_('../math/Vec3');
        var Transform = _dereq_('../math/Transform');
        var RaycastResult = _dereq_('../collision/RaycastResult');
        var Utils = _dereq_('../utils/Utils');
        module.exports = WheelInfo;
        function WheelInfo(options) {
          options = Utils.defaults(options, {
            chassisConnectionPointLocal: new Vec3(),
            chassisConnectionPointWorld: new Vec3(),
            directionLocal: new Vec3(),
            directionWorld: new Vec3(),
            axleLocal: new Vec3(),
            axleWorld: new Vec3(),
            suspensionRestLength: 1,
            suspensionMaxLength: 2,
            radius: 1,
            suspensionStiffness: 100,
            dampingCompression: 10,
            dampingRelaxation: 10,
            frictionSlip: 10000,
            steering: 0,
            rotation: 0,
            deltaRotation: 0,
            rollInfluence: 0.01,
            maxSuspensionForce: Number.MAX_VALUE,
            isFrontWheel: true,
            clippedInvContactDotSuspension: 1,
            suspensionRelativeVelocity: 0,
            suspensionForce: 0,
            skidInfo: 0,
            suspensionLength: 0,
            maxSuspensionTravel: 1,
            useCustomSlidingRotationalSpeed: false,
            customSlidingRotationalSpeed: -0.1
          });
          this.maxSuspensionTravel = options.maxSuspensionTravel;
          this.customSlidingRotationalSpeed = options.customSlidingRotationalSpeed;
          this.useCustomSlidingRotationalSpeed = options.useCustomSlidingRotationalSpeed;
          this.sliding = false;
          this.chassisConnectionPointLocal = options.chassisConnectionPointLocal.clone();
          this.chassisConnectionPointWorld = options.chassisConnectionPointWorld.clone();
          this.directionLocal = options.directionLocal.clone();
          this.directionWorld = options.directionWorld.clone();
          this.axleLocal = options.axleLocal.clone();
          this.axleWorld = options.axleWorld.clone();
          this.suspensionRestLength = options.suspensionRestLength;
          this.suspensionMaxLength = options.suspensionMaxLength;
          this.radius = options.radius;
          this.suspensionStiffness = options.suspensionStiffness;
          this.dampingCompression = options.dampingCompression;
          this.dampingRelaxation = options.dampingRelaxation;
          this.frictionSlip = options.frictionSlip;
          this.steering = 0;
          this.rotation = 0;
          this.deltaRotation = 0;
          this.rollInfluence = options.rollInfluence;
          this.maxSuspensionForce = options.maxSuspensionForce;
          this.engineForce = 0;
          this.brake = 0;
          this.isFrontWheel = options.isFrontWheel;
          this.clippedInvContactDotSuspension = 1;
          this.suspensionRelativeVelocity = 0;
          this.suspensionForce = 0;
          this.skidInfo = 0;
          this.suspensionLength = 0;
          this.sideImpulse = 0;
          this.forwardImpulse = 0;
          this.raycastResult = new RaycastResult();
          this.worldTransform = new Transform();
          this.isInContact = false;
        }
        var chassis_velocity_at_contactPoint = new Vec3();
        var relpos = new Vec3();
        var chassis_velocity_at_contactPoint = new Vec3();
        WheelInfo.prototype.updateWheel = function(chassis) {
          var raycastResult = this.raycastResult;
          if (this.isInContact) {
            var project = raycastResult.hitNormalWorld.dot(raycastResult.directionWorld);
            raycastResult.hitPointWorld.vsub(chassis.position, relpos);
            chassis.getVelocityAtWorldPoint(relpos, chassis_velocity_at_contactPoint);
            var projVel = raycastResult.hitNormalWorld.dot(chassis_velocity_at_contactPoint);
            if (project >= -0.1) {
              this.suspensionRelativeVelocity = 0.0;
              this.clippedInvContactDotSuspension = 1.0 / 0.1;
            } else {
              var inv = -1 / project;
              this.suspensionRelativeVelocity = projVel * inv;
              this.clippedInvContactDotSuspension = inv;
            }
          } else {
            raycastResult.suspensionLength = this.suspensionRestLength;
            this.suspensionRelativeVelocity = 0.0;
            raycastResult.directionWorld.scale(-1, raycastResult.hitNormalWorld);
            this.clippedInvContactDotSuspension = 1.0;
          }
        };
      }, {
        "../collision/RaycastResult": 10,
        "../math/Transform": 29,
        "../math/Vec3": 30,
        "../utils/Utils": 53
      }],
      37: [function(_dereq_, module, exports) {
        module.exports = Box;
        var Shape = _dereq_('./Shape');
        var Vec3 = _dereq_('../math/Vec3');
        var ConvexPolyhedron = _dereq_('./ConvexPolyhedron');
        function Box(halfExtents) {
          Shape.call(this);
          this.type = Shape.types.BOX;
          this.halfExtents = halfExtents;
          this.convexPolyhedronRepresentation = null;
          this.updateConvexPolyhedronRepresentation();
          this.updateBoundingSphereRadius();
        }
        Box.prototype = new Shape();
        Box.prototype.constructor = Box;
        Box.prototype.updateConvexPolyhedronRepresentation = function() {
          var sx = this.halfExtents.x;
          var sy = this.halfExtents.y;
          var sz = this.halfExtents.z;
          var V = Vec3;
          var vertices = [new V(-sx, -sy, -sz), new V(sx, -sy, -sz), new V(sx, sy, -sz), new V(-sx, sy, -sz), new V(-sx, -sy, sz), new V(sx, -sy, sz), new V(sx, sy, sz), new V(-sx, sy, sz)];
          var indices = [[3, 2, 1, 0], [4, 5, 6, 7], [5, 4, 0, 1], [2, 3, 7, 6], [0, 4, 7, 3], [1, 2, 6, 5]];
          var axes = [new V(0, 0, 1), new V(0, 1, 0), new V(1, 0, 0)];
          var h = new ConvexPolyhedron(vertices, indices);
          this.convexPolyhedronRepresentation = h;
          h.material = this.material;
        };
        Box.prototype.calculateLocalInertia = function(mass, target) {
          target = target || new Vec3();
          Box.calculateInertia(this.halfExtents, mass, target);
          return target;
        };
        Box.calculateInertia = function(halfExtents, mass, target) {
          var e = halfExtents;
          target.x = 1.0 / 12.0 * mass * (2 * e.y * 2 * e.y + 2 * e.z * 2 * e.z);
          target.y = 1.0 / 12.0 * mass * (2 * e.x * 2 * e.x + 2 * e.z * 2 * e.z);
          target.z = 1.0 / 12.0 * mass * (2 * e.y * 2 * e.y + 2 * e.x * 2 * e.x);
        };
        Box.prototype.getSideNormals = function(sixTargetVectors, quat) {
          var sides = sixTargetVectors;
          var ex = this.halfExtents;
          sides[0].set(ex.x, 0, 0);
          sides[1].set(0, ex.y, 0);
          sides[2].set(0, 0, ex.z);
          sides[3].set(-ex.x, 0, 0);
          sides[4].set(0, -ex.y, 0);
          sides[5].set(0, 0, -ex.z);
          if (quat !== undefined) {
            for (var i = 0; i !== sides.length; i++) {
              quat.vmult(sides[i], sides[i]);
            }
          }
          return sides;
        };
        Box.prototype.volume = function() {
          return 8.0 * this.halfExtents.x * this.halfExtents.y * this.halfExtents.z;
        };
        Box.prototype.updateBoundingSphereRadius = function() {
          this.boundingSphereRadius = this.halfExtents.norm();
        };
        var worldCornerTempPos = new Vec3();
        var worldCornerTempNeg = new Vec3();
        Box.prototype.forEachWorldCorner = function(pos, quat, callback) {
          var e = this.halfExtents;
          var corners = [[e.x, e.y, e.z], [-e.x, e.y, e.z], [-e.x, -e.y, e.z], [-e.x, -e.y, -e.z], [e.x, -e.y, -e.z], [e.x, e.y, -e.z], [-e.x, e.y, -e.z], [e.x, -e.y, e.z]];
          for (var i = 0; i < corners.length; i++) {
            worldCornerTempPos.set(corners[i][0], corners[i][1], corners[i][2]);
            quat.vmult(worldCornerTempPos, worldCornerTempPos);
            pos.vadd(worldCornerTempPos, worldCornerTempPos);
            callback(worldCornerTempPos.x, worldCornerTempPos.y, worldCornerTempPos.z);
          }
        };
        var worldCornersTemp = [new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3()];
        Box.prototype.calculateWorldAABB = function(pos, quat, min, max) {
          var e = this.halfExtents;
          worldCornersTemp[0].set(e.x, e.y, e.z);
          worldCornersTemp[1].set(-e.x, e.y, e.z);
          worldCornersTemp[2].set(-e.x, -e.y, e.z);
          worldCornersTemp[3].set(-e.x, -e.y, -e.z);
          worldCornersTemp[4].set(e.x, -e.y, -e.z);
          worldCornersTemp[5].set(e.x, e.y, -e.z);
          worldCornersTemp[6].set(-e.x, e.y, -e.z);
          worldCornersTemp[7].set(e.x, -e.y, e.z);
          var wc = worldCornersTemp[0];
          quat.vmult(wc, wc);
          pos.vadd(wc, wc);
          max.copy(wc);
          min.copy(wc);
          for (var i = 1; i < 8; i++) {
            var wc = worldCornersTemp[i];
            quat.vmult(wc, wc);
            pos.vadd(wc, wc);
            var x = wc.x;
            var y = wc.y;
            var z = wc.z;
            if (x > max.x) {
              max.x = x;
            }
            if (y > max.y) {
              max.y = y;
            }
            if (z > max.z) {
              max.z = z;
            }
            if (x < min.x) {
              min.x = x;
            }
            if (y < min.y) {
              min.y = y;
            }
            if (z < min.z) {
              min.z = z;
            }
          }
        };
      }, {
        "../math/Vec3": 30,
        "./ConvexPolyhedron": 38,
        "./Shape": 43
      }],
      38: [function(_dereq_, module, exports) {
        module.exports = ConvexPolyhedron;
        var Shape = _dereq_('./Shape');
        var Vec3 = _dereq_('../math/Vec3');
        var Quaternion = _dereq_('../math/Quaternion');
        var Transform = _dereq_('../math/Transform');
        function ConvexPolyhedron(points, faces, uniqueAxes) {
          var that = this;
          Shape.call(this);
          this.type = Shape.types.CONVEXPOLYHEDRON;
          this.vertices = points || [];
          this.worldVertices = [];
          this.worldVerticesNeedsUpdate = true;
          this.faces = faces || [];
          this.faceNormals = [];
          this.computeNormals();
          this.worldFaceNormalsNeedsUpdate = true;
          this.worldFaceNormals = [];
          this.uniqueEdges = [];
          this.uniqueAxes = uniqueAxes ? uniqueAxes.slice() : null;
          this.computeEdges();
          this.updateBoundingSphereRadius();
        }
        ConvexPolyhedron.prototype = new Shape();
        ConvexPolyhedron.prototype.constructor = ConvexPolyhedron;
        var computeEdges_tmpEdge = new Vec3();
        ConvexPolyhedron.prototype.computeEdges = function() {
          var faces = this.faces;
          var vertices = this.vertices;
          var nv = vertices.length;
          var edges = this.uniqueEdges;
          edges.length = 0;
          var edge = computeEdges_tmpEdge;
          for (var i = 0; i !== faces.length; i++) {
            var face = faces[i];
            var numVertices = face.length;
            for (var j = 0; j !== numVertices; j++) {
              var k = (j + 1) % numVertices;
              vertices[face[j]].vsub(vertices[face[k]], edge);
              edge.normalize();
              var found = false;
              for (var p = 0; p !== edges.length; p++) {
                if (edges[p].almostEquals(edge) || edges[p].almostEquals(edge)) {
                  found = true;
                  break;
                }
              }
              if (!found) {
                edges.push(edge.clone());
              }
            }
          }
        };
        ConvexPolyhedron.prototype.computeNormals = function() {
          this.faceNormals.length = this.faces.length;
          for (var i = 0; i < this.faces.length; i++) {
            for (var j = 0; j < this.faces[i].length; j++) {
              if (!this.vertices[this.faces[i][j]]) {
                throw new Error("Vertex " + this.faces[i][j] + " not found!");
              }
            }
            var n = this.faceNormals[i] || new Vec3();
            this.getFaceNormal(i, n);
            n.negate(n);
            this.faceNormals[i] = n;
            var vertex = this.vertices[this.faces[i][0]];
            if (n.dot(vertex) < 0) {
              console.error(".faceNormals[" + i + "] = Vec3(" + n.toString() + ") looks like it points into the shape? The vertices follow. Make sure they are ordered CCW around the normal, using the right hand rule.");
              for (var j = 0; j < this.faces[i].length; j++) {
                console.warn(".vertices[" + this.faces[i][j] + "] = Vec3(" + this.vertices[this.faces[i][j]].toString() + ")");
              }
            }
          }
        };
        var cb = new Vec3();
        var ab = new Vec3();
        ConvexPolyhedron.computeNormal = function(va, vb, vc, target) {
          vb.vsub(va, ab);
          vc.vsub(vb, cb);
          cb.cross(ab, target);
          if (!target.isZero()) {
            target.normalize();
          }
        };
        ConvexPolyhedron.prototype.getFaceNormal = function(i, target) {
          var f = this.faces[i];
          var va = this.vertices[f[0]];
          var vb = this.vertices[f[1]];
          var vc = this.vertices[f[2]];
          return ConvexPolyhedron.computeNormal(va, vb, vc, target);
        };
        var cah_WorldNormal = new Vec3();
        ConvexPolyhedron.prototype.clipAgainstHull = function(posA, quatA, hullB, posB, quatB, separatingNormal, minDist, maxDist, result) {
          var WorldNormal = cah_WorldNormal;
          var hullA = this;
          var curMaxDist = maxDist;
          var closestFaceB = -1;
          var dmax = -Number.MAX_VALUE;
          for (var face = 0; face < hullB.faces.length; face++) {
            WorldNormal.copy(hullB.faceNormals[face]);
            quatB.vmult(WorldNormal, WorldNormal);
            var d = WorldNormal.dot(separatingNormal);
            if (d > dmax) {
              dmax = d;
              closestFaceB = face;
            }
          }
          var worldVertsB1 = [];
          var polyB = hullB.faces[closestFaceB];
          var numVertices = polyB.length;
          for (var e0 = 0; e0 < numVertices; e0++) {
            var b = hullB.vertices[polyB[e0]];
            var worldb = new Vec3();
            worldb.copy(b);
            quatB.vmult(worldb, worldb);
            posB.vadd(worldb, worldb);
            worldVertsB1.push(worldb);
          }
          if (closestFaceB >= 0) {
            this.clipFaceAgainstHull(separatingNormal, posA, quatA, worldVertsB1, minDist, maxDist, result);
          }
        };
        var fsa_faceANormalWS3 = new Vec3(),
            fsa_Worldnormal1 = new Vec3(),
            fsa_deltaC = new Vec3(),
            fsa_worldEdge0 = new Vec3(),
            fsa_worldEdge1 = new Vec3(),
            fsa_Cross = new Vec3();
        ConvexPolyhedron.prototype.findSeparatingAxis = function(hullB, posA, quatA, posB, quatB, target, faceListA, faceListB) {
          var faceANormalWS3 = fsa_faceANormalWS3,
              Worldnormal1 = fsa_Worldnormal1,
              deltaC = fsa_deltaC,
              worldEdge0 = fsa_worldEdge0,
              worldEdge1 = fsa_worldEdge1,
              Cross = fsa_Cross;
          var dmin = Number.MAX_VALUE;
          var hullA = this;
          var curPlaneTests = 0;
          if (!hullA.uniqueAxes) {
            var numFacesA = faceListA ? faceListA.length : hullA.faces.length;
            for (var i = 0; i < numFacesA; i++) {
              var fi = faceListA ? faceListA[i] : i;
              faceANormalWS3.copy(hullA.faceNormals[fi]);
              quatA.vmult(faceANormalWS3, faceANormalWS3);
              var d = hullA.testSepAxis(faceANormalWS3, hullB, posA, quatA, posB, quatB);
              if (d === false) {
                return false;
              }
              if (d < dmin) {
                dmin = d;
                target.copy(faceANormalWS3);
              }
            }
          } else {
            for (var i = 0; i !== hullA.uniqueAxes.length; i++) {
              quatA.vmult(hullA.uniqueAxes[i], faceANormalWS3);
              var d = hullA.testSepAxis(faceANormalWS3, hullB, posA, quatA, posB, quatB);
              if (d === false) {
                return false;
              }
              if (d < dmin) {
                dmin = d;
                target.copy(faceANormalWS3);
              }
            }
          }
          if (!hullB.uniqueAxes) {
            var numFacesB = faceListB ? faceListB.length : hullB.faces.length;
            for (var i = 0; i < numFacesB; i++) {
              var fi = faceListB ? faceListB[i] : i;
              Worldnormal1.copy(hullB.faceNormals[fi]);
              quatB.vmult(Worldnormal1, Worldnormal1);
              curPlaneTests++;
              var d = hullA.testSepAxis(Worldnormal1, hullB, posA, quatA, posB, quatB);
              if (d === false) {
                return false;
              }
              if (d < dmin) {
                dmin = d;
                target.copy(Worldnormal1);
              }
            }
          } else {
            for (var i = 0; i !== hullB.uniqueAxes.length; i++) {
              quatB.vmult(hullB.uniqueAxes[i], Worldnormal1);
              curPlaneTests++;
              var d = hullA.testSepAxis(Worldnormal1, hullB, posA, quatA, posB, quatB);
              if (d === false) {
                return false;
              }
              if (d < dmin) {
                dmin = d;
                target.copy(Worldnormal1);
              }
            }
          }
          for (var e0 = 0; e0 !== hullA.uniqueEdges.length; e0++) {
            quatA.vmult(hullA.uniqueEdges[e0], worldEdge0);
            for (var e1 = 0; e1 !== hullB.uniqueEdges.length; e1++) {
              quatB.vmult(hullB.uniqueEdges[e1], worldEdge1);
              worldEdge0.cross(worldEdge1, Cross);
              if (!Cross.almostZero()) {
                Cross.normalize();
                var dist = hullA.testSepAxis(Cross, hullB, posA, quatA, posB, quatB);
                if (dist === false) {
                  return false;
                }
                if (dist < dmin) {
                  dmin = dist;
                  target.copy(Cross);
                }
              }
            }
          }
          posB.vsub(posA, deltaC);
          if ((deltaC.dot(target)) > 0.0) {
            target.negate(target);
          }
          return true;
        };
        var maxminA = [],
            maxminB = [];
        ConvexPolyhedron.prototype.testSepAxis = function(axis, hullB, posA, quatA, posB, quatB) {
          var hullA = this;
          ConvexPolyhedron.project(hullA, axis, posA, quatA, maxminA);
          ConvexPolyhedron.project(hullB, axis, posB, quatB, maxminB);
          var maxA = maxminA[0];
          var minA = maxminA[1];
          var maxB = maxminB[0];
          var minB = maxminB[1];
          if (maxA < minB || maxB < minA) {
            return false;
          }
          var d0 = maxA - minB;
          var d1 = maxB - minA;
          var depth = d0 < d1 ? d0 : d1;
          return depth;
        };
        var cli_aabbmin = new Vec3(),
            cli_aabbmax = new Vec3();
        ConvexPolyhedron.prototype.calculateLocalInertia = function(mass, target) {
          this.computeLocalAABB(cli_aabbmin, cli_aabbmax);
          var x = cli_aabbmax.x - cli_aabbmin.x,
              y = cli_aabbmax.y - cli_aabbmin.y,
              z = cli_aabbmax.z - cli_aabbmin.z;
          target.x = 1.0 / 12.0 * mass * (2 * y * 2 * y + 2 * z * 2 * z);
          target.y = 1.0 / 12.0 * mass * (2 * x * 2 * x + 2 * z * 2 * z);
          target.z = 1.0 / 12.0 * mass * (2 * y * 2 * y + 2 * x * 2 * x);
        };
        ConvexPolyhedron.prototype.getPlaneConstantOfFace = function(face_i) {
          var f = this.faces[face_i];
          var n = this.faceNormals[face_i];
          var v = this.vertices[f[0]];
          var c = -n.dot(v);
          return c;
        };
        var cfah_faceANormalWS = new Vec3(),
            cfah_edge0 = new Vec3(),
            cfah_WorldEdge0 = new Vec3(),
            cfah_worldPlaneAnormal1 = new Vec3(),
            cfah_planeNormalWS1 = new Vec3(),
            cfah_worldA1 = new Vec3(),
            cfah_localPlaneNormal = new Vec3(),
            cfah_planeNormalWS = new Vec3();
        ConvexPolyhedron.prototype.clipFaceAgainstHull = function(separatingNormal, posA, quatA, worldVertsB1, minDist, maxDist, result) {
          var faceANormalWS = cfah_faceANormalWS,
              edge0 = cfah_edge0,
              WorldEdge0 = cfah_WorldEdge0,
              worldPlaneAnormal1 = cfah_worldPlaneAnormal1,
              planeNormalWS1 = cfah_planeNormalWS1,
              worldA1 = cfah_worldA1,
              localPlaneNormal = cfah_localPlaneNormal,
              planeNormalWS = cfah_planeNormalWS;
          var hullA = this;
          var worldVertsB2 = [];
          var pVtxIn = worldVertsB1;
          var pVtxOut = worldVertsB2;
          var closestFaceA = -1;
          var dmin = Number.MAX_VALUE;
          for (var face = 0; face < hullA.faces.length; face++) {
            faceANormalWS.copy(hullA.faceNormals[face]);
            quatA.vmult(faceANormalWS, faceANormalWS);
            var d = faceANormalWS.dot(separatingNormal);
            if (d < dmin) {
              dmin = d;
              closestFaceA = face;
            }
          }
          if (closestFaceA < 0) {
            return;
          }
          var polyA = hullA.faces[closestFaceA];
          polyA.connectedFaces = [];
          for (var i = 0; i < hullA.faces.length; i++) {
            for (var j = 0; j < hullA.faces[i].length; j++) {
              if (polyA.indexOf(hullA.faces[i][j]) !== -1 && i !== closestFaceA && polyA.connectedFaces.indexOf(i) === -1) {
                polyA.connectedFaces.push(i);
              }
            }
          }
          var numContacts = pVtxIn.length;
          var numVerticesA = polyA.length;
          var res = [];
          for (var e0 = 0; e0 < numVerticesA; e0++) {
            var a = hullA.vertices[polyA[e0]];
            var b = hullA.vertices[polyA[(e0 + 1) % numVerticesA]];
            a.vsub(b, edge0);
            WorldEdge0.copy(edge0);
            quatA.vmult(WorldEdge0, WorldEdge0);
            posA.vadd(WorldEdge0, WorldEdge0);
            worldPlaneAnormal1.copy(this.faceNormals[closestFaceA]);
            quatA.vmult(worldPlaneAnormal1, worldPlaneAnormal1);
            posA.vadd(worldPlaneAnormal1, worldPlaneAnormal1);
            WorldEdge0.cross(worldPlaneAnormal1, planeNormalWS1);
            planeNormalWS1.negate(planeNormalWS1);
            worldA1.copy(a);
            quatA.vmult(worldA1, worldA1);
            posA.vadd(worldA1, worldA1);
            var planeEqWS1 = -worldA1.dot(planeNormalWS1);
            var planeEqWS;
            if (true) {
              var otherFace = polyA.connectedFaces[e0];
              localPlaneNormal.copy(this.faceNormals[otherFace]);
              var localPlaneEq = this.getPlaneConstantOfFace(otherFace);
              planeNormalWS.copy(localPlaneNormal);
              quatA.vmult(planeNormalWS, planeNormalWS);
              var planeEqWS = localPlaneEq - planeNormalWS.dot(posA);
            } else {
              planeNormalWS.copy(planeNormalWS1);
              planeEqWS = planeEqWS1;
            }
            this.clipFaceAgainstPlane(pVtxIn, pVtxOut, planeNormalWS, planeEqWS);
            while (pVtxIn.length) {
              pVtxIn.shift();
            }
            while (pVtxOut.length) {
              pVtxIn.push(pVtxOut.shift());
            }
          }
          localPlaneNormal.copy(this.faceNormals[closestFaceA]);
          var localPlaneEq = this.getPlaneConstantOfFace(closestFaceA);
          planeNormalWS.copy(localPlaneNormal);
          quatA.vmult(planeNormalWS, planeNormalWS);
          var planeEqWS = localPlaneEq - planeNormalWS.dot(posA);
          for (var i = 0; i < pVtxIn.length; i++) {
            var depth = planeNormalWS.dot(pVtxIn[i]) + planeEqWS;
            if (depth <= minDist) {
              console.log("clamped: depth=" + depth + " to minDist=" + (minDist + ""));
              depth = minDist;
            }
            if (depth <= maxDist) {
              var point = pVtxIn[i];
              if (depth <= 0) {
                var p = {
                  point: point,
                  normal: planeNormalWS,
                  depth: depth
                };
                result.push(p);
              }
            }
          }
        };
        ConvexPolyhedron.prototype.clipFaceAgainstPlane = function(inVertices, outVertices, planeNormal, planeConstant) {
          var n_dot_first,
              n_dot_last;
          var numVerts = inVertices.length;
          if (numVerts < 2) {
            return outVertices;
          }
          var firstVertex = inVertices[inVertices.length - 1],
              lastVertex = inVertices[0];
          n_dot_first = planeNormal.dot(firstVertex) + planeConstant;
          for (var vi = 0; vi < numVerts; vi++) {
            lastVertex = inVertices[vi];
            n_dot_last = planeNormal.dot(lastVertex) + planeConstant;
            if (n_dot_first < 0) {
              if (n_dot_last < 0) {
                var newv = new Vec3();
                newv.copy(lastVertex);
                outVertices.push(newv);
              } else {
                var newv = new Vec3();
                firstVertex.lerp(lastVertex, n_dot_first / (n_dot_first - n_dot_last), newv);
                outVertices.push(newv);
              }
            } else {
              if (n_dot_last < 0) {
                var newv = new Vec3();
                firstVertex.lerp(lastVertex, n_dot_first / (n_dot_first - n_dot_last), newv);
                outVertices.push(newv);
                outVertices.push(lastVertex);
              }
            }
            firstVertex = lastVertex;
            n_dot_first = n_dot_last;
          }
          return outVertices;
        };
        ConvexPolyhedron.prototype.computeWorldVertices = function(position, quat) {
          var N = this.vertices.length;
          while (this.worldVertices.length < N) {
            this.worldVertices.push(new Vec3());
          }
          var verts = this.vertices,
              worldVerts = this.worldVertices;
          for (var i = 0; i !== N; i++) {
            quat.vmult(verts[i], worldVerts[i]);
            position.vadd(worldVerts[i], worldVerts[i]);
          }
          this.worldVerticesNeedsUpdate = false;
        };
        var computeLocalAABB_worldVert = new Vec3();
        ConvexPolyhedron.prototype.computeLocalAABB = function(aabbmin, aabbmax) {
          var n = this.vertices.length,
              vertices = this.vertices,
              worldVert = computeLocalAABB_worldVert;
          aabbmin.set(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
          aabbmax.set(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE);
          for (var i = 0; i < n; i++) {
            var v = vertices[i];
            if (v.x < aabbmin.x) {
              aabbmin.x = v.x;
            } else if (v.x > aabbmax.x) {
              aabbmax.x = v.x;
            }
            if (v.y < aabbmin.y) {
              aabbmin.y = v.y;
            } else if (v.y > aabbmax.y) {
              aabbmax.y = v.y;
            }
            if (v.z < aabbmin.z) {
              aabbmin.z = v.z;
            } else if (v.z > aabbmax.z) {
              aabbmax.z = v.z;
            }
          }
        };
        ConvexPolyhedron.prototype.computeWorldFaceNormals = function(quat) {
          var N = this.faceNormals.length;
          while (this.worldFaceNormals.length < N) {
            this.worldFaceNormals.push(new Vec3());
          }
          var normals = this.faceNormals,
              worldNormals = this.worldFaceNormals;
          for (var i = 0; i !== N; i++) {
            quat.vmult(normals[i], worldNormals[i]);
          }
          this.worldFaceNormalsNeedsUpdate = false;
        };
        ConvexPolyhedron.prototype.updateBoundingSphereRadius = function() {
          var max2 = 0;
          var verts = this.vertices;
          for (var i = 0,
              N = verts.length; i !== N; i++) {
            var norm2 = verts[i].norm2();
            if (norm2 > max2) {
              max2 = norm2;
            }
          }
          this.boundingSphereRadius = Math.sqrt(max2);
        };
        var tempWorldVertex = new Vec3();
        ConvexPolyhedron.prototype.calculateWorldAABB = function(pos, quat, min, max) {
          var n = this.vertices.length,
              verts = this.vertices;
          var minx,
              miny,
              minz,
              maxx,
              maxy,
              maxz;
          for (var i = 0; i < n; i++) {
            tempWorldVertex.copy(verts[i]);
            quat.vmult(tempWorldVertex, tempWorldVertex);
            pos.vadd(tempWorldVertex, tempWorldVertex);
            var v = tempWorldVertex;
            if (v.x < minx || minx === undefined) {
              minx = v.x;
            } else if (v.x > maxx || maxx === undefined) {
              maxx = v.x;
            }
            if (v.y < miny || miny === undefined) {
              miny = v.y;
            } else if (v.y > maxy || maxy === undefined) {
              maxy = v.y;
            }
            if (v.z < minz || minz === undefined) {
              minz = v.z;
            } else if (v.z > maxz || maxz === undefined) {
              maxz = v.z;
            }
          }
          min.set(minx, miny, minz);
          max.set(maxx, maxy, maxz);
        };
        ConvexPolyhedron.prototype.volume = function() {
          return 4.0 * Math.PI * this.boundingSphereRadius / 3.0;
        };
        ConvexPolyhedron.prototype.getAveragePointLocal = function(target) {
          target = target || new Vec3();
          var n = this.vertices.length,
              verts = this.vertices;
          for (var i = 0; i < n; i++) {
            target.vadd(verts[i], target);
          }
          target.mult(1 / n, target);
          return target;
        };
        ConvexPolyhedron.prototype.transformAllPoints = function(offset, quat) {
          var n = this.vertices.length,
              verts = this.vertices;
          if (quat) {
            for (var i = 0; i < n; i++) {
              var v = verts[i];
              quat.vmult(v, v);
            }
            for (var i = 0; i < this.faceNormals.length; i++) {
              var v = this.faceNormals[i];
              quat.vmult(v, v);
            }
          }
          if (offset) {
            for (var i = 0; i < n; i++) {
              var v = verts[i];
              v.vadd(offset, v);
            }
          }
        };
        var ConvexPolyhedron_pointIsInside = new Vec3();
        var ConvexPolyhedron_vToP = new Vec3();
        var ConvexPolyhedron_vToPointInside = new Vec3();
        ConvexPolyhedron.prototype.pointIsInside = function(p) {
          var n = this.vertices.length,
              verts = this.vertices,
              faces = this.faces,
              normals = this.faceNormals;
          var positiveResult = null;
          var N = this.faces.length;
          var pointInside = ConvexPolyhedron_pointIsInside;
          this.getAveragePointLocal(pointInside);
          for (var i = 0; i < N; i++) {
            var numVertices = this.faces[i].length;
            var n = normals[i];
            var v = verts[faces[i][0]];
            var vToP = ConvexPolyhedron_vToP;
            p.vsub(v, vToP);
            var r1 = n.dot(vToP);
            var vToPointInside = ConvexPolyhedron_vToPointInside;
            pointInside.vsub(v, vToPointInside);
            var r2 = n.dot(vToPointInside);
            if ((r1 < 0 && r2 > 0) || (r1 > 0 && r2 < 0)) {
              return false;
            } else {}
          }
          return positiveResult ? 1 : -1;
        };
        var project_worldVertex = new Vec3();
        var project_localAxis = new Vec3();
        var project_localOrigin = new Vec3();
        ConvexPolyhedron.project = function(hull, axis, pos, quat, result) {
          var n = hull.vertices.length,
              worldVertex = project_worldVertex,
              localAxis = project_localAxis,
              max = 0,
              min = 0,
              localOrigin = project_localOrigin,
              vs = hull.vertices;
          localOrigin.setZero();
          Transform.vectorToLocalFrame(pos, quat, axis, localAxis);
          Transform.pointToLocalFrame(pos, quat, localOrigin, localOrigin);
          var add = localOrigin.dot(localAxis);
          min = max = vs[0].dot(localAxis);
          for (var i = 1; i < n; i++) {
            var val = vs[i].dot(localAxis);
            if (val > max) {
              max = val;
            }
            if (val < min) {
              min = val;
            }
          }
          min -= add;
          max -= add;
          if (min > max) {
            var temp = min;
            min = max;
            max = temp;
          }
          result[0] = max;
          result[1] = min;
        };
      }, {
        "../math/Quaternion": 28,
        "../math/Transform": 29,
        "../math/Vec3": 30,
        "./Shape": 43
      }],
      39: [function(_dereq_, module, exports) {
        module.exports = Cylinder;
        var Shape = _dereq_('./Shape');
        var Vec3 = _dereq_('../math/Vec3');
        var Quaternion = _dereq_('../math/Quaternion');
        var ConvexPolyhedron = _dereq_('./ConvexPolyhedron');
        function Cylinder(radiusTop, radiusBottom, height, numSegments) {
          var N = numSegments,
              verts = [],
              axes = [],
              faces = [],
              bottomface = [],
              topface = [],
              cos = Math.cos,
              sin = Math.sin;
          verts.push(new Vec3(radiusBottom * cos(0), radiusBottom * sin(0), -height * 0.5));
          bottomface.push(0);
          verts.push(new Vec3(radiusTop * cos(0), radiusTop * sin(0), height * 0.5));
          topface.push(1);
          for (var i = 0; i < N; i++) {
            var theta = 2 * Math.PI / N * (i + 1);
            var thetaN = 2 * Math.PI / N * (i + 0.5);
            if (i < N - 1) {
              verts.push(new Vec3(radiusBottom * cos(theta), radiusBottom * sin(theta), -height * 0.5));
              bottomface.push(2 * i + 2);
              verts.push(new Vec3(radiusTop * cos(theta), radiusTop * sin(theta), height * 0.5));
              topface.push(2 * i + 3);
              faces.push([2 * i + 2, 2 * i + 3, 2 * i + 1, 2 * i]);
            } else {
              faces.push([0, 1, 2 * i + 1, 2 * i]);
            }
            if (N % 2 === 1 || i < N / 2) {
              axes.push(new Vec3(cos(thetaN), sin(thetaN), 0));
            }
          }
          faces.push(topface);
          axes.push(new Vec3(0, 0, 1));
          var temp = [];
          for (var i = 0; i < bottomface.length; i++) {
            temp.push(bottomface[bottomface.length - i - 1]);
          }
          faces.push(temp);
          this.type = Shape.types.CONVEXPOLYHEDRON;
          ConvexPolyhedron.call(this, verts, faces, axes);
        }
        Cylinder.prototype = new ConvexPolyhedron();
      }, {
        "../math/Quaternion": 28,
        "../math/Vec3": 30,
        "./ConvexPolyhedron": 38,
        "./Shape": 43
      }],
      40: [function(_dereq_, module, exports) {
        var Shape = _dereq_('./Shape');
        var ConvexPolyhedron = _dereq_('./ConvexPolyhedron');
        var Vec3 = _dereq_('../math/Vec3');
        var Utils = _dereq_('../utils/Utils');
        module.exports = Heightfield;
        function Heightfield(data, options) {
          options = Utils.defaults(options, {
            maxValue: null,
            minValue: null,
            elementSize: 1
          });
          this.data = data;
          this.maxValue = options.maxValue;
          this.minValue = options.minValue;
          this.elementSize = options.elementSize;
          if (options.minValue === null) {
            this.updateMinValue();
          }
          if (options.maxValue === null) {
            this.updateMaxValue();
          }
          this.cacheEnabled = true;
          Shape.call(this);
          this.pillarConvex = new ConvexPolyhedron();
          this.pillarOffset = new Vec3();
          this.type = Shape.types.HEIGHTFIELD;
          this.updateBoundingSphereRadius();
          this._cachedPillars = {};
        }
        Heightfield.prototype = new Shape();
        Heightfield.prototype.update = function() {
          this._cachedPillars = {};
        };
        Heightfield.prototype.updateMinValue = function() {
          var data = this.data;
          var minValue = data[0][0];
          for (var i = 0; i !== data.length; i++) {
            for (var j = 0; j !== data[i].length; j++) {
              var v = data[i][j];
              if (v < minValue) {
                minValue = v;
              }
            }
          }
          this.minValue = minValue;
        };
        Heightfield.prototype.updateMaxValue = function() {
          var data = this.data;
          var maxValue = data[0][0];
          for (var i = 0; i !== data.length; i++) {
            for (var j = 0; j !== data[i].length; j++) {
              var v = data[i][j];
              if (v > maxValue) {
                maxValue = v;
              }
            }
          }
          this.maxValue = maxValue;
        };
        Heightfield.prototype.setHeightValueAtIndex = function(xi, yi, value) {
          var data = this.data;
          data[xi][yi] = value;
          this.clearCachedConvexTrianglePillar(xi, yi, false);
          if (xi > 0) {
            this.clearCachedConvexTrianglePillar(xi - 1, yi, true);
            this.clearCachedConvexTrianglePillar(xi - 1, yi, false);
          }
          if (yi > 0) {
            this.clearCachedConvexTrianglePillar(xi, yi - 1, true);
            this.clearCachedConvexTrianglePillar(xi, yi - 1, false);
          }
          if (yi > 0 && xi > 0) {
            this.clearCachedConvexTrianglePillar(xi - 1, yi - 1, true);
          }
        };
        Heightfield.prototype.getRectMinMax = function(iMinX, iMinY, iMaxX, iMaxY, result) {
          result = result || [];
          var data = this.data,
              max = this.minValue;
          for (var i = iMinX; i <= iMaxX; i++) {
            for (var j = iMinY; j <= iMaxY; j++) {
              var height = data[i][j];
              if (height > max) {
                max = height;
              }
            }
          }
          result[0] = this.minValue;
          result[1] = max;
        };
        Heightfield.prototype.getIndexOfPosition = function(x, y, result, clamp) {
          var w = this.elementSize;
          var data = this.data;
          var xi = Math.floor(x / w);
          var yi = Math.floor(y / w);
          result[0] = xi;
          result[1] = yi;
          if (clamp) {
            if (xi < 0) {
              xi = 0;
            }
            if (yi < 0) {
              yi = 0;
            }
            if (xi >= data.length - 1) {
              xi = data.length - 1;
            }
            if (yi >= data[0].length - 1) {
              yi = data[0].length - 1;
            }
          }
          if (xi < 0 || yi < 0 || xi >= data.length - 1 || yi >= data[0].length - 1) {
            return false;
          }
          return true;
        };
        Heightfield.prototype.getHeightAt = function(x, y, edgeClamp) {
          var idx = [];
          this.getIndexOfPosition(x, y, idx, edgeClamp);
          var minmax = [];
          this.getRectMinMax(idx[0], idx[1] + 1, idx[0], idx[1] + 1, minmax);
          return (minmax[0] + minmax[1]) / 2;
        };
        Heightfield.prototype.getCacheConvexTrianglePillarKey = function(xi, yi, getUpperTriangle) {
          return xi + '_' + yi + '_' + (getUpperTriangle ? 1 : 0);
        };
        Heightfield.prototype.getCachedConvexTrianglePillar = function(xi, yi, getUpperTriangle) {
          return this._cachedPillars[this.getCacheConvexTrianglePillarKey(xi, yi, getUpperTriangle)];
        };
        Heightfield.prototype.setCachedConvexTrianglePillar = function(xi, yi, getUpperTriangle, convex, offset) {
          this._cachedPillars[this.getCacheConvexTrianglePillarKey(xi, yi, getUpperTriangle)] = {
            convex: convex,
            offset: offset
          };
        };
        Heightfield.prototype.clearCachedConvexTrianglePillar = function(xi, yi, getUpperTriangle) {
          delete this._cachedPillars[this.getCacheConvexTrianglePillarKey(xi, yi, getUpperTriangle)];
        };
        Heightfield.prototype.getConvexTrianglePillar = function(xi, yi, getUpperTriangle) {
          var result = this.pillarConvex;
          var offsetResult = this.pillarOffset;
          if (this.cacheEnabled) {
            var data = this.getCachedConvexTrianglePillar(xi, yi, getUpperTriangle);
            if (data) {
              this.pillarConvex = data.convex;
              this.pillarOffset = data.offset;
              return;
            }
            result = new ConvexPolyhedron();
            offsetResult = new Vec3();
            this.pillarConvex = result;
            this.pillarOffset = offsetResult;
          }
          var data = this.data;
          var elementSize = this.elementSize;
          var faces = result.faces;
          result.vertices.length = 6;
          for (var i = 0; i < 6; i++) {
            if (!result.vertices[i]) {
              result.vertices[i] = new Vec3();
            }
          }
          faces.length = 5;
          for (var i = 0; i < 5; i++) {
            if (!faces[i]) {
              faces[i] = [];
            }
          }
          var verts = result.vertices;
          var h = (Math.min(data[xi][yi], data[xi + 1][yi], data[xi][yi + 1], data[xi + 1][yi + 1]) - this.minValue) / 2 + this.minValue;
          if (!getUpperTriangle) {
            offsetResult.set((xi + 0.25) * elementSize, (yi + 0.25) * elementSize, h);
            verts[0].set(-0.25 * elementSize, -0.25 * elementSize, data[xi][yi] - h);
            verts[1].set(0.75 * elementSize, -0.25 * elementSize, data[xi + 1][yi] - h);
            verts[2].set(-0.25 * elementSize, 0.75 * elementSize, data[xi][yi + 1] - h);
            verts[3].set(-0.25 * elementSize, -0.25 * elementSize, -h - 1);
            verts[4].set(0.75 * elementSize, -0.25 * elementSize, -h - 1);
            verts[5].set(-0.25 * elementSize, 0.75 * elementSize, -h - 1);
            faces[0][0] = 0;
            faces[0][1] = 1;
            faces[0][2] = 2;
            faces[1][0] = 5;
            faces[1][1] = 4;
            faces[1][2] = 3;
            faces[2][0] = 0;
            faces[2][1] = 2;
            faces[2][2] = 5;
            faces[2][3] = 3;
            faces[3][0] = 1;
            faces[3][1] = 0;
            faces[3][2] = 3;
            faces[3][3] = 4;
            faces[4][0] = 4;
            faces[4][1] = 5;
            faces[4][2] = 2;
            faces[4][3] = 1;
          } else {
            offsetResult.set((xi + 0.75) * elementSize, (yi + 0.75) * elementSize, h);
            verts[0].set(0.25 * elementSize, 0.25 * elementSize, data[xi + 1][yi + 1] - h);
            verts[1].set(-0.75 * elementSize, 0.25 * elementSize, data[xi][yi + 1] - h);
            verts[2].set(0.25 * elementSize, -0.75 * elementSize, data[xi + 1][yi] - h);
            verts[3].set(0.25 * elementSize, 0.25 * elementSize, -h - 1);
            verts[4].set(-0.75 * elementSize, 0.25 * elementSize, -h - 1);
            verts[5].set(0.25 * elementSize, -0.75 * elementSize, -h - 1);
            faces[0][0] = 0;
            faces[0][1] = 1;
            faces[0][2] = 2;
            faces[1][0] = 5;
            faces[1][1] = 4;
            faces[1][2] = 3;
            faces[2][0] = 2;
            faces[2][1] = 5;
            faces[2][2] = 3;
            faces[2][3] = 0;
            faces[3][0] = 3;
            faces[3][1] = 4;
            faces[3][2] = 1;
            faces[3][3] = 0;
            faces[4][0] = 1;
            faces[4][1] = 4;
            faces[4][2] = 5;
            faces[4][3] = 2;
          }
          result.computeNormals();
          result.computeEdges();
          result.updateBoundingSphereRadius();
          this.setCachedConvexTrianglePillar(xi, yi, getUpperTriangle, result, offsetResult);
        };
        Heightfield.prototype.calculateLocalInertia = function(mass, target) {
          target = target || new Vec3();
          target.set(0, 0, 0);
          return target;
        };
        Heightfield.prototype.volume = function() {
          return Number.MAX_VALUE;
        };
        Heightfield.prototype.calculateWorldAABB = function(pos, quat, min, max) {
          min.set(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE);
          max.set(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE);
        };
        Heightfield.prototype.updateBoundingSphereRadius = function() {
          var data = this.data,
              s = this.elementSize;
          this.boundingSphereRadius = new Vec3(data.length * s, data[0].length * s, Math.max(Math.abs(this.maxValue), Math.abs(this.minValue))).norm();
        };
      }, {
        "../math/Vec3": 30,
        "../utils/Utils": 53,
        "./ConvexPolyhedron": 38,
        "./Shape": 43
      }],
      41: [function(_dereq_, module, exports) {
        module.exports = Particle;
        var Shape = _dereq_('./Shape');
        var Vec3 = _dereq_('../math/Vec3');
        function Particle() {
          Shape.call(this);
          this.type = Shape.types.PARTICLE;
        }
        Particle.prototype = new Shape();
        Particle.prototype.constructor = Particle;
        Particle.prototype.calculateLocalInertia = function(mass, target) {
          target = target || new Vec3();
          target.set(0, 0, 0);
          return target;
        };
        Particle.prototype.volume = function() {
          return 0;
        };
        Particle.prototype.updateBoundingSphereRadius = function() {
          this.boundingSphereRadius = 0;
        };
        Particle.prototype.calculateWorldAABB = function(pos, quat, min, max) {
          min.copy(pos);
          max.copy(pos);
        };
      }, {
        "../math/Vec3": 30,
        "./Shape": 43
      }],
      42: [function(_dereq_, module, exports) {
        module.exports = Plane;
        var Shape = _dereq_('./Shape');
        var Vec3 = _dereq_('../math/Vec3');
        function Plane() {
          Shape.call(this);
          this.type = Shape.types.PLANE;
          this.worldNormal = new Vec3();
          this.worldNormalNeedsUpdate = true;
          this.boundingSphereRadius = Number.MAX_VALUE;
        }
        Plane.prototype = new Shape();
        Plane.prototype.constructor = Plane;
        Plane.prototype.computeWorldNormal = function(quat) {
          var n = this.worldNormal;
          n.set(0, 0, 1);
          quat.vmult(n, n);
          this.worldNormalNeedsUpdate = false;
        };
        Plane.prototype.calculateLocalInertia = function(mass, target) {
          target = target || new Vec3();
          return target;
        };
        Plane.prototype.volume = function() {
          return Number.MAX_VALUE;
        };
        var tempNormal = new Vec3();
        Plane.prototype.calculateWorldAABB = function(pos, quat, min, max) {
          tempNormal.set(0, 0, 1);
          quat.vmult(tempNormal, tempNormal);
          var maxVal = Number.MAX_VALUE;
          min.set(-maxVal, -maxVal, -maxVal);
          max.set(maxVal, maxVal, maxVal);
          if (tempNormal.x === 1) {
            max.x = pos.x;
          }
          if (tempNormal.y === 1) {
            max.y = pos.y;
          }
          if (tempNormal.z === 1) {
            max.z = pos.z;
          }
          if (tempNormal.x === -1) {
            min.x = pos.x;
          }
          if (tempNormal.y === -1) {
            min.y = pos.y;
          }
          if (tempNormal.z === -1) {
            min.z = pos.z;
          }
        };
        Plane.prototype.updateBoundingSphereRadius = function() {
          this.boundingSphereRadius = Number.MAX_VALUE;
        };
      }, {
        "../math/Vec3": 30,
        "./Shape": 43
      }],
      43: [function(_dereq_, module, exports) {
        module.exports = Shape;
        var Shape = _dereq_('./Shape');
        var Vec3 = _dereq_('../math/Vec3');
        var Quaternion = _dereq_('../math/Quaternion');
        var Material = _dereq_('../material/Material');
        function Shape() {
          this.id = Shape.idCounter++;
          this.type = 0;
          this.boundingSphereRadius = 0;
          this.collisionResponse = true;
          this.material = null;
        }
        Shape.prototype.constructor = Shape;
        Shape.prototype.updateBoundingSphereRadius = function() {
          throw "computeBoundingSphereRadius() not implemented for shape type " + this.type;
        };
        Shape.prototype.volume = function() {
          throw "volume() not implemented for shape type " + this.type;
        };
        Shape.prototype.calculateLocalInertia = function(mass, target) {
          throw "calculateLocalInertia() not implemented for shape type " + this.type;
        };
        Shape.idCounter = 0;
        Shape.types = {
          SPHERE: 1,
          PLANE: 2,
          BOX: 4,
          COMPOUND: 8,
          CONVEXPOLYHEDRON: 16,
          HEIGHTFIELD: 32,
          PARTICLE: 64,
          CYLINDER: 128,
          TRIMESH: 256
        };
      }, {
        "../material/Material": 25,
        "../math/Quaternion": 28,
        "../math/Vec3": 30,
        "./Shape": 43
      }],
      44: [function(_dereq_, module, exports) {
        module.exports = Sphere;
        var Shape = _dereq_('./Shape');
        var Vec3 = _dereq_('../math/Vec3');
        function Sphere(radius) {
          Shape.call(this);
          this.radius = radius !== undefined ? Number(radius) : 1.0;
          this.type = Shape.types.SPHERE;
          if (this.radius < 0) {
            throw new Error('The sphere radius cannot be negative.');
          }
          this.updateBoundingSphereRadius();
        }
        Sphere.prototype = new Shape();
        Sphere.prototype.constructor = Sphere;
        Sphere.prototype.calculateLocalInertia = function(mass, target) {
          target = target || new Vec3();
          var I = 2.0 * mass * this.radius * this.radius / 5.0;
          target.x = I;
          target.y = I;
          target.z = I;
          return target;
        };
        Sphere.prototype.volume = function() {
          return 4.0 * Math.PI * this.radius / 3.0;
        };
        Sphere.prototype.updateBoundingSphereRadius = function() {
          this.boundingSphereRadius = this.radius;
        };
        Sphere.prototype.calculateWorldAABB = function(pos, quat, min, max) {
          var r = this.radius;
          var axes = ['x', 'y', 'z'];
          for (var i = 0; i < axes.length; i++) {
            var ax = axes[i];
            min[ax] = pos[ax] - r;
            max[ax] = pos[ax] + r;
          }
        };
      }, {
        "../math/Vec3": 30,
        "./Shape": 43
      }],
      45: [function(_dereq_, module, exports) {
        module.exports = Trimesh;
        var Shape = _dereq_('./Shape');
        var Vec3 = _dereq_('../math/Vec3');
        var Quaternion = _dereq_('../math/Quaternion');
        var Transform = _dereq_('../math/Transform');
        var AABB = _dereq_('../collision/AABB');
        var Octree = _dereq_('../utils/Octree');
        function Trimesh(vertices, indices) {
          Shape.call(this);
          this.type = Shape.types.TRIMESH;
          this.vertices = new Float32Array(vertices);
          this.indices = new Int16Array(indices);
          this.normals = new Float32Array(indices.length);
          this.aabb = new AABB();
          this.edges = null;
          this.scale = new Vec3(1, 1, 1);
          this.tree = new Octree();
          this.updateEdges();
          this.updateNormals();
          this.updateAABB();
          this.updateBoundingSphereRadius();
          this.updateTree();
        }
        Trimesh.prototype = new Shape();
        Trimesh.prototype.constructor = Trimesh;
        var computeNormals_n = new Vec3();
        Trimesh.prototype.updateTree = function() {
          var tree = this.tree;
          tree.reset();
          tree.aabb.copy(this.aabb);
          var scale = this.scale;
          tree.aabb.lowerBound.x *= 1 / scale.x;
          tree.aabb.lowerBound.y *= 1 / scale.y;
          tree.aabb.lowerBound.z *= 1 / scale.z;
          tree.aabb.upperBound.x *= 1 / scale.x;
          tree.aabb.upperBound.y *= 1 / scale.y;
          tree.aabb.upperBound.z *= 1 / scale.z;
          var triangleAABB = new AABB();
          var a = new Vec3();
          var b = new Vec3();
          var c = new Vec3();
          var points = [a, b, c];
          for (var i = 0; i < this.indices.length / 3; i++) {
            var i3 = i * 3;
            this._getUnscaledVertex(this.indices[i3], a);
            this._getUnscaledVertex(this.indices[i3 + 1], b);
            this._getUnscaledVertex(this.indices[i3 + 2], c);
            triangleAABB.setFromPoints(points);
            tree.insert(triangleAABB, i);
          }
          tree.removeEmptyNodes();
        };
        var unscaledAABB = new AABB();
        Trimesh.prototype.getTrianglesInAABB = function(aabb, result) {
          unscaledAABB.copy(aabb);
          var scale = this.scale;
          var isx = scale.x;
          var isy = scale.y;
          var isz = scale.z;
          var l = unscaledAABB.lowerBound;
          var u = unscaledAABB.upperBound;
          l.x /= isx;
          l.y /= isy;
          l.z /= isz;
          u.x /= isx;
          u.y /= isy;
          u.z /= isz;
          return this.tree.aabbQuery(unscaledAABB, result);
        };
        Trimesh.prototype.setScale = function(scale) {
          var wasUniform = this.scale.x === this.scale.y === this.scale.z;
          var isUniform = scale.x === scale.y === scale.z;
          if (!(wasUniform && isUniform)) {
            this.updateNormals();
          }
          this.scale.copy(scale);
          this.updateAABB();
          this.updateBoundingSphereRadius();
        };
        Trimesh.prototype.updateNormals = function() {
          var n = computeNormals_n;
          var normals = this.normals;
          for (var i = 0; i < this.indices.length / 3; i++) {
            var i3 = i * 3;
            var a = this.indices[i3],
                b = this.indices[i3 + 1],
                c = this.indices[i3 + 2];
            this.getVertex(a, va);
            this.getVertex(b, vb);
            this.getVertex(c, vc);
            Trimesh.computeNormal(vb, va, vc, n);
            normals[i3] = n.x;
            normals[i3 + 1] = n.y;
            normals[i3 + 2] = n.z;
          }
        };
        Trimesh.prototype.updateEdges = function() {
          var edges = {};
          var add = function(indexA, indexB) {
            var key = a < b ? a + '_' + b : b + '_' + a;
            edges[key] = true;
          };
          for (var i = 0; i < this.indices.length / 3; i++) {
            var i3 = i * 3;
            var a = this.indices[i3],
                b = this.indices[i3 + 1],
                c = this.indices[i3 + 2];
            add(a, b);
            add(b, c);
            add(c, a);
          }
          var keys = Object.keys(edges);
          this.edges = new Int16Array(keys.length * 2);
          for (var i = 0; i < keys.length; i++) {
            var indices = keys[i].split('_');
            this.edges[2 * i] = parseInt(indices[0], 10);
            this.edges[2 * i + 1] = parseInt(indices[1], 10);
          }
        };
        Trimesh.prototype.getEdgeVertex = function(edgeIndex, firstOrSecond, vertexStore) {
          var vertexIndex = this.edges[edgeIndex * 2 + (firstOrSecond ? 1 : 0)];
          this.getVertex(vertexIndex, vertexStore);
        };
        var getEdgeVector_va = new Vec3();
        var getEdgeVector_vb = new Vec3();
        Trimesh.prototype.getEdgeVector = function(edgeIndex, vectorStore) {
          var va = getEdgeVector_va;
          var vb = getEdgeVector_vb;
          this.getEdgeVertex(edgeIndex, 0, va);
          this.getEdgeVertex(edgeIndex, 1, vb);
          vb.vsub(va, vectorStore);
        };
        var cb = new Vec3();
        var ab = new Vec3();
        Trimesh.computeNormal = function(va, vb, vc, target) {
          vb.vsub(va, ab);
          vc.vsub(vb, cb);
          cb.cross(ab, target);
          if (!target.isZero()) {
            target.normalize();
          }
        };
        var va = new Vec3();
        var vb = new Vec3();
        var vc = new Vec3();
        Trimesh.prototype.getVertex = function(i, out) {
          var scale = this.scale;
          this._getUnscaledVertex(i, out);
          out.x *= scale.x;
          out.y *= scale.y;
          out.z *= scale.z;
          return out;
        };
        Trimesh.prototype._getUnscaledVertex = function(i, out) {
          var i3 = i * 3;
          var vertices = this.vertices;
          return out.set(vertices[i3], vertices[i3 + 1], vertices[i3 + 2]);
        };
        Trimesh.prototype.getWorldVertex = function(i, pos, quat, out) {
          this.getVertex(i, out);
          Transform.pointToWorldFrame(pos, quat, out, out);
          return out;
        };
        Trimesh.prototype.getTriangleVertices = function(i, a, b, c) {
          var i3 = i * 3;
          this.getVertex(this.indices[i3], a);
          this.getVertex(this.indices[i3 + 1], b);
          this.getVertex(this.indices[i3 + 2], c);
        };
        Trimesh.prototype.getNormal = function(i, target) {
          var i3 = i * 3;
          return target.set(this.normals[i3], this.normals[i3 + 1], this.normals[i3 + 2]);
        };
        var cli_aabb = new AABB();
        Trimesh.prototype.calculateLocalInertia = function(mass, target) {
          this.computeLocalAABB(cli_aabb);
          var x = cli_aabb.upperBound.x - cli_aabb.lowerBound.x,
              y = cli_aabb.upperBound.y - cli_aabb.lowerBound.y,
              z = cli_aabb.upperBound.z - cli_aabb.lowerBound.z;
          return target.set(1.0 / 12.0 * mass * (2 * y * 2 * y + 2 * z * 2 * z), 1.0 / 12.0 * mass * (2 * x * 2 * x + 2 * z * 2 * z), 1.0 / 12.0 * mass * (2 * y * 2 * y + 2 * x * 2 * x));
        };
        var computeLocalAABB_worldVert = new Vec3();
        Trimesh.prototype.computeLocalAABB = function(aabb) {
          var l = aabb.lowerBound,
              u = aabb.upperBound,
              n = this.vertices.length,
              vertices = this.vertices,
              v = computeLocalAABB_worldVert;
          this.getVertex(0, v);
          l.copy(v);
          u.copy(v);
          for (var i = 0; i !== n; i++) {
            this.getVertex(i, v);
            if (v.x < l.x) {
              l.x = v.x;
            } else if (v.x > u.x) {
              u.x = v.x;
            }
            if (v.y < l.y) {
              l.y = v.y;
            } else if (v.y > u.y) {
              u.y = v.y;
            }
            if (v.z < l.z) {
              l.z = v.z;
            } else if (v.z > u.z) {
              u.z = v.z;
            }
          }
        };
        Trimesh.prototype.updateAABB = function() {
          this.computeLocalAABB(this.aabb);
        };
        Trimesh.prototype.updateBoundingSphereRadius = function() {
          var max2 = 0;
          var vertices = this.vertices;
          var v = new Vec3();
          for (var i = 0,
              N = vertices.length / 3; i !== N; i++) {
            this.getVertex(i, v);
            var norm2 = v.norm2();
            if (norm2 > max2) {
              max2 = norm2;
            }
          }
          this.boundingSphereRadius = Math.sqrt(max2);
        };
        var tempWorldVertex = new Vec3();
        var calculateWorldAABB_frame = new Transform();
        var calculateWorldAABB_aabb = new AABB();
        Trimesh.prototype.calculateWorldAABB = function(pos, quat, min, max) {
          var frame = calculateWorldAABB_frame;
          var result = calculateWorldAABB_aabb;
          frame.position = pos;
          frame.quaternion = quat;
          this.aabb.toWorldFrame(frame, result);
          min.copy(result.lowerBound);
          max.copy(result.upperBound);
        };
        Trimesh.prototype.volume = function() {
          return 4.0 * Math.PI * this.boundingSphereRadius / 3.0;
        };
        Trimesh.createTorus = function(radius, tube, radialSegments, tubularSegments, arc) {
          radius = radius || 1;
          tube = tube || 0.5;
          radialSegments = radialSegments || 8;
          tubularSegments = tubularSegments || 6;
          arc = arc || Math.PI * 2;
          var vertices = [];
          var indices = [];
          for (var j = 0; j <= radialSegments; j++) {
            for (var i = 0; i <= tubularSegments; i++) {
              var u = i / tubularSegments * arc;
              var v = j / radialSegments * Math.PI * 2;
              var x = (radius + tube * Math.cos(v)) * Math.cos(u);
              var y = (radius + tube * Math.cos(v)) * Math.sin(u);
              var z = tube * Math.sin(v);
              vertices.push(x, y, z);
            }
          }
          for (var j = 1; j <= radialSegments; j++) {
            for (var i = 1; i <= tubularSegments; i++) {
              var a = (tubularSegments + 1) * j + i - 1;
              var b = (tubularSegments + 1) * (j - 1) + i - 1;
              var c = (tubularSegments + 1) * (j - 1) + i;
              var d = (tubularSegments + 1) * j + i;
              indices.push(a, b, d);
              indices.push(b, c, d);
            }
          }
          return new Trimesh(vertices, indices);
        };
      }, {
        "../collision/AABB": 3,
        "../math/Quaternion": 28,
        "../math/Transform": 29,
        "../math/Vec3": 30,
        "../utils/Octree": 50,
        "./Shape": 43
      }],
      46: [function(_dereq_, module, exports) {
        module.exports = GSSolver;
        var Vec3 = _dereq_('../math/Vec3');
        var Quaternion = _dereq_('../math/Quaternion');
        var Solver = _dereq_('./Solver');
        function GSSolver() {
          Solver.call(this);
          this.iterations = 10;
          this.tolerance = 1e-7;
        }
        GSSolver.prototype = new Solver();
        var GSSolver_solve_lambda = [];
        var GSSolver_solve_invCs = [];
        var GSSolver_solve_Bs = [];
        GSSolver.prototype.solve = function(dt, world) {
          var iter = 0,
              maxIter = this.iterations,
              tolSquared = this.tolerance * this.tolerance,
              equations = this.equations,
              Neq = equations.length,
              bodies = world.bodies,
              Nbodies = bodies.length,
              h = dt,
              q,
              B,
              invC,
              deltalambda,
              deltalambdaTot,
              GWlambda,
              lambdaj;
          if (Neq !== 0) {
            for (var i = 0; i !== Nbodies; i++) {
              bodies[i].updateSolveMassProperties();
            }
          }
          var invCs = GSSolver_solve_invCs,
              Bs = GSSolver_solve_Bs,
              lambda = GSSolver_solve_lambda;
          invCs.length = Neq;
          Bs.length = Neq;
          lambda.length = Neq;
          for (var i = 0; i !== Neq; i++) {
            var c = equations[i];
            lambda[i] = 0.0;
            Bs[i] = c.computeB(h);
            invCs[i] = 1.0 / c.computeC();
          }
          if (Neq !== 0) {
            for (var i = 0; i !== Nbodies; i++) {
              var b = bodies[i],
                  vlambda = b.vlambda,
                  wlambda = b.wlambda;
              vlambda.set(0, 0, 0);
              if (wlambda) {
                wlambda.set(0, 0, 0);
              }
            }
            for (iter = 0; iter !== maxIter; iter++) {
              deltalambdaTot = 0.0;
              for (var j = 0; j !== Neq; j++) {
                var c = equations[j];
                B = Bs[j];
                invC = invCs[j];
                lambdaj = lambda[j];
                GWlambda = c.computeGWlambda();
                deltalambda = invC * (B - GWlambda - c.eps * lambdaj);
                if (lambdaj + deltalambda < c.minForce) {
                  deltalambda = c.minForce - lambdaj;
                } else if (lambdaj + deltalambda > c.maxForce) {
                  deltalambda = c.maxForce - lambdaj;
                }
                lambda[j] += deltalambda;
                deltalambdaTot += deltalambda > 0.0 ? deltalambda : -deltalambda;
                c.addToWlambda(deltalambda);
              }
              if (deltalambdaTot * deltalambdaTot < tolSquared) {
                break;
              }
            }
            for (var i = 0; i !== Nbodies; i++) {
              var b = bodies[i],
                  v = b.velocity,
                  w = b.angularVelocity;
              v.vadd(b.vlambda, v);
              if (w) {
                w.vadd(b.wlambda, w);
              }
            }
          }
          return iter;
        };
      }, {
        "../math/Quaternion": 28,
        "../math/Vec3": 30,
        "./Solver": 47
      }],
      47: [function(_dereq_, module, exports) {
        module.exports = Solver;
        function Solver() {
          this.equations = [];
        }
        Solver.prototype.solve = function(dt, world) {
          return 0;
        };
        Solver.prototype.addEquation = function(eq) {
          if (eq.enabled) {
            this.equations.push(eq);
          }
        };
        Solver.prototype.removeEquation = function(eq) {
          var eqs = this.equations;
          var i = eqs.indexOf(eq);
          if (i !== -1) {
            eqs.splice(i, 1);
          }
        };
        Solver.prototype.removeAllEquations = function() {
          this.equations.length = 0;
        };
      }, {}],
      48: [function(_dereq_, module, exports) {
        module.exports = SplitSolver;
        var Vec3 = _dereq_('../math/Vec3');
        var Quaternion = _dereq_('../math/Quaternion');
        var Solver = _dereq_('./Solver');
        var Body = _dereq_('../objects/Body');
        function SplitSolver(subsolver) {
          Solver.call(this);
          this.iterations = 10;
          this.tolerance = 1e-7;
          this.subsolver = subsolver;
          this.nodes = [];
          this.nodePool = [];
          while (this.nodePool.length < 128) {
            this.nodePool.push(this.createNode());
          }
        }
        SplitSolver.prototype = new Solver();
        var SplitSolver_solve_nodes = [];
        var SplitSolver_solve_nodePool = [];
        var SplitSolver_solve_eqs = [];
        var SplitSolver_solve_bds = [];
        var SplitSolver_solve_dummyWorld = {bodies: []};
        var STATIC = Body.STATIC;
        function getUnvisitedNode(nodes) {
          var Nnodes = nodes.length;
          for (var i = 0; i !== Nnodes; i++) {
            var node = nodes[i];
            if (!node.visited && !(node.body.type & STATIC)) {
              return node;
            }
          }
          return false;
        }
        var queue = [];
        function bfs(root, visitFunc, bds, eqs) {
          queue.push(root);
          root.visited = true;
          visitFunc(root, bds, eqs);
          while (queue.length) {
            var node = queue.pop();
            var child;
            while ((child = getUnvisitedNode(node.children))) {
              child.visited = true;
              visitFunc(child, bds, eqs);
              queue.push(child);
            }
          }
        }
        function visitFunc(node, bds, eqs) {
          bds.push(node.body);
          var Neqs = node.eqs.length;
          for (var i = 0; i !== Neqs; i++) {
            var eq = node.eqs[i];
            if (eqs.indexOf(eq) === -1) {
              eqs.push(eq);
            }
          }
        }
        SplitSolver.prototype.createNode = function() {
          return {
            body: null,
            children: [],
            eqs: [],
            visited: false
          };
        };
        SplitSolver.prototype.solve = function(dt, world) {
          var nodes = SplitSolver_solve_nodes,
              nodePool = this.nodePool,
              bodies = world.bodies,
              equations = this.equations,
              Neq = equations.length,
              Nbodies = bodies.length,
              subsolver = this.subsolver;
          while (nodePool.length < Nbodies) {
            nodePool.push(this.createNode());
          }
          nodes.length = Nbodies;
          for (var i = 0; i < Nbodies; i++) {
            nodes[i] = nodePool[i];
          }
          for (var i = 0; i !== Nbodies; i++) {
            var node = nodes[i];
            node.body = bodies[i];
            node.children.length = 0;
            node.eqs.length = 0;
            node.visited = false;
          }
          for (var k = 0; k !== Neq; k++) {
            var eq = equations[k],
                i = bodies.indexOf(eq.bi),
                j = bodies.indexOf(eq.bj),
                ni = nodes[i],
                nj = nodes[j];
            ni.children.push(nj);
            ni.eqs.push(eq);
            nj.children.push(ni);
            nj.eqs.push(eq);
          }
          var child,
              n = 0,
              eqs = SplitSolver_solve_eqs;
          subsolver.tolerance = this.tolerance;
          subsolver.iterations = this.iterations;
          var dummyWorld = SplitSolver_solve_dummyWorld;
          while ((child = getUnvisitedNode(nodes))) {
            eqs.length = 0;
            dummyWorld.bodies.length = 0;
            bfs(child, visitFunc, dummyWorld.bodies, eqs);
            var Neqs = eqs.length;
            eqs = eqs.sort(sortById);
            for (var i = 0; i !== Neqs; i++) {
              subsolver.addEquation(eqs[i]);
            }
            var iter = subsolver.solve(dt, dummyWorld);
            subsolver.removeAllEquations();
            n++;
          }
          return n;
        };
        function sortById(a, b) {
          return b.id - a.id;
        }
      }, {
        "../math/Quaternion": 28,
        "../math/Vec3": 30,
        "../objects/Body": 31,
        "./Solver": 47
      }],
      49: [function(_dereq_, module, exports) {
        var EventTarget = function() {};
        module.exports = EventTarget;
        EventTarget.prototype = {
          constructor: EventTarget,
          addEventListener: function(type, listener) {
            if (this._listeners === undefined) {
              this._listeners = {};
            }
            var listeners = this._listeners;
            if (listeners[type] === undefined) {
              listeners[type] = [];
            }
            if (listeners[type].indexOf(listener) === -1) {
              listeners[type].push(listener);
            }
            return this;
          },
          hasEventListener: function(type, listener) {
            if (this._listeners === undefined) {
              return false;
            }
            var listeners = this._listeners;
            if (listeners[type] !== undefined && listeners[type].indexOf(listener) !== -1) {
              return true;
            }
            return false;
          },
          removeEventListener: function(type, listener) {
            if (this._listeners === undefined) {
              return this;
            }
            var listeners = this._listeners;
            if (listeners[type] === undefined) {
              return this;
            }
            var index = listeners[type].indexOf(listener);
            if (index !== -1) {
              listeners[type].splice(index, 1);
            }
            return this;
          },
          dispatchEvent: function(event) {
            if (this._listeners === undefined) {
              return this;
            }
            var listeners = this._listeners;
            var listenerArray = listeners[event.type];
            if (listenerArray !== undefined) {
              event.target = this;
              for (var i = 0,
                  l = listenerArray.length; i < l; i++) {
                listenerArray[i].call(this, event);
              }
            }
            return this;
          }
        };
      }, {}],
      50: [function(_dereq_, module, exports) {
        var AABB = _dereq_('../collision/AABB');
        var Vec3 = _dereq_('../math/Vec3');
        module.exports = Octree;
        function OctreeNode(options) {
          options = options || {};
          this.root = options.root || null;
          this.aabb = options.aabb ? options.aabb.clone() : new AABB();
          this.data = [];
          this.children = [];
        }
        function Octree(aabb, options) {
          options = options || {};
          options.root = null;
          options.aabb = aabb;
          OctreeNode.call(this, options);
          this.maxDepth = typeof(options.maxDepth) !== 'undefined' ? options.maxDepth : 8;
        }
        Octree.prototype = new OctreeNode();
        OctreeNode.prototype.reset = function(aabb, options) {
          this.children.length = this.data.length = 0;
        };
        OctreeNode.prototype.insert = function(aabb, elementData, level) {
          var nodeData = this.data;
          level = level || 0;
          if (!this.aabb.contains(aabb)) {
            return false;
          }
          var children = this.children;
          if (level < (this.maxDepth || this.root.maxDepth)) {
            var subdivided = false;
            if (!children.length) {
              this.subdivide();
              subdivided = true;
            }
            for (var i = 0; i !== 8; i++) {
              if (children[i].insert(aabb, elementData, level + 1)) {
                return true;
              }
            }
            if (subdivided) {
              children.length = 0;
            }
          }
          nodeData.push(elementData);
          return true;
        };
        var halfDiagonal = new Vec3();
        OctreeNode.prototype.subdivide = function() {
          var aabb = this.aabb;
          var l = aabb.lowerBound;
          var u = aabb.upperBound;
          var children = this.children;
          children.push(new OctreeNode({aabb: new AABB({lowerBound: new Vec3(0, 0, 0)})}), new OctreeNode({aabb: new AABB({lowerBound: new Vec3(1, 0, 0)})}), new OctreeNode({aabb: new AABB({lowerBound: new Vec3(1, 1, 0)})}), new OctreeNode({aabb: new AABB({lowerBound: new Vec3(1, 1, 1)})}), new OctreeNode({aabb: new AABB({lowerBound: new Vec3(0, 1, 1)})}), new OctreeNode({aabb: new AABB({lowerBound: new Vec3(0, 0, 1)})}), new OctreeNode({aabb: new AABB({lowerBound: new Vec3(1, 0, 1)})}), new OctreeNode({aabb: new AABB({lowerBound: new Vec3(0, 1, 0)})}));
          u.vsub(l, halfDiagonal);
          halfDiagonal.scale(0.5, halfDiagonal);
          var root = this.root || this;
          for (var i = 0; i !== 8; i++) {
            var child = children[i];
            child.root = root;
            var lowerBound = child.aabb.lowerBound;
            lowerBound.x *= halfDiagonal.x;
            lowerBound.y *= halfDiagonal.y;
            lowerBound.z *= halfDiagonal.z;
            lowerBound.vadd(l, lowerBound);
            lowerBound.vadd(halfDiagonal, child.aabb.upperBound);
          }
        };
        OctreeNode.prototype.aabbQuery = function(aabb, result) {
          var nodeData = this.data;
          var children = this.children;
          var queue = [this];
          while (queue.length) {
            var node = queue.pop();
            if (node.aabb.overlaps(aabb)) {
              Array.prototype.push.apply(result, node.data);
            }
            Array.prototype.push.apply(queue, node.children);
          }
          return result;
        };
        var tmpAABB = new AABB();
        OctreeNode.prototype.rayQuery = function(ray, treeTransform, result) {
          ray.getAABB(tmpAABB);
          tmpAABB.toLocalFrame(treeTransform, tmpAABB);
          this.aabbQuery(tmpAABB, result);
          return result;
        };
        OctreeNode.prototype.removeEmptyNodes = function() {
          var queue = [this];
          while (queue.length) {
            var node = queue.pop();
            for (var i = node.children.length - 1; i >= 0; i--) {
              if (!node.children[i].data.length) {
                node.children.splice(i, 1);
              }
            }
            Array.prototype.push.apply(queue, node.children);
          }
        };
      }, {
        "../collision/AABB": 3,
        "../math/Vec3": 30
      }],
      51: [function(_dereq_, module, exports) {
        module.exports = Pool;
        function Pool() {
          this.objects = [];
          this.type = Object;
        }
        Pool.prototype.release = function() {
          var Nargs = arguments.length;
          for (var i = 0; i !== Nargs; i++) {
            this.objects.push(arguments[i]);
          }
        };
        Pool.prototype.get = function() {
          if (this.objects.length === 0) {
            return this.constructObject();
          } else {
            return this.objects.pop();
          }
        };
        Pool.prototype.constructObject = function() {
          throw new Error("constructObject() not implemented in this Pool subclass yet!");
        };
      }, {}],
      52: [function(_dereq_, module, exports) {
        module.exports = TupleDictionary;
        function TupleDictionary() {
          this.data = {keys: []};
        }
        TupleDictionary.prototype.get = function(i, j) {
          if (i > j) {
            var temp = j;
            j = i;
            i = temp;
          }
          return this.data[i + '-' + j];
        };
        TupleDictionary.prototype.set = function(i, j, value) {
          if (i > j) {
            var temp = j;
            j = i;
            i = temp;
          }
          var key = i + '-' + j;
          if (!this.get(i, j)) {
            this.data.keys.push(key);
          }
          this.data[key] = value;
        };
        TupleDictionary.prototype.reset = function() {
          var data = this.data,
              keys = data.keys;
          while (keys.length > 0) {
            var key = keys.pop();
            delete data[key];
          }
        };
      }, {}],
      53: [function(_dereq_, module, exports) {
        function Utils() {}
        module.exports = Utils;
        Utils.defaults = function(options, defaults) {
          options = options || {};
          for (var key in defaults) {
            if (!(key in options)) {
              options[key] = defaults[key];
            }
          }
          return options;
        };
      }, {}],
      54: [function(_dereq_, module, exports) {
        module.exports = Vec3Pool;
        var Vec3 = _dereq_('../math/Vec3');
        var Pool = _dereq_('./Pool');
        function Vec3Pool() {
          Pool.call(this);
          this.type = Vec3;
        }
        Vec3Pool.prototype = new Pool();
        Vec3Pool.prototype.constructObject = function() {
          return new Vec3();
        };
      }, {
        "../math/Vec3": 30,
        "./Pool": 51
      }],
      55: [function(_dereq_, module, exports) {
        module.exports = Narrowphase;
        var AABB = _dereq_('../collision/AABB');
        var Shape = _dereq_('../shapes/Shape');
        var Ray = _dereq_('../collision/Ray');
        var Vec3 = _dereq_('../math/Vec3');
        var Transform = _dereq_('../math/Transform');
        var ConvexPolyhedron = _dereq_('../shapes/ConvexPolyhedron');
        var Quaternion = _dereq_('../math/Quaternion');
        var Solver = _dereq_('../solver/Solver');
        var Vec3Pool = _dereq_('../utils/Vec3Pool');
        var ContactEquation = _dereq_('../equations/ContactEquation');
        var FrictionEquation = _dereq_('../equations/FrictionEquation');
        function Narrowphase(world) {
          this.contactPointPool = [];
          this.frictionEquationPool = [];
          this.result = [];
          this.frictionResult = [];
          this.v3pool = new Vec3Pool();
          this.world = world;
          this.currentContactMaterial = null;
          this.enableFrictionReduction = false;
        }
        Narrowphase.prototype.createContactEquation = function(bi, bj, si, sj, rsi, rsj) {
          var c;
          if (this.contactPointPool.length) {
            c = this.contactPointPool.pop();
            c.bi = bi;
            c.bj = bj;
          } else {
            c = new ContactEquation(bi, bj);
          }
          c.enabled = bi.collisionResponse && bj.collisionResponse && si.collisionResponse && sj.collisionResponse;
          var cm = this.currentContactMaterial;
          c.restitution = cm.restitution;
          c.setSpookParams(cm.contactEquationStiffness, cm.contactEquationRelaxation, this.world.dt);
          var matA = si.material || bi.material;
          var matB = sj.material || bj.material;
          if (matA && matB && matA.restitution >= 0 && matB.restitution >= 0) {
            c.restitution = matA.restitution * matB.restitution;
          }
          c.si = rsi || si;
          c.sj = rsj || sj;
          return c;
        };
        Narrowphase.prototype.createFrictionEquationsFromContact = function(contactEquation, outArray) {
          var bodyA = contactEquation.bi;
          var bodyB = contactEquation.bj;
          var shapeA = contactEquation.si;
          var shapeB = contactEquation.sj;
          var world = this.world;
          var cm = this.currentContactMaterial;
          var friction = cm.friction;
          var matA = shapeA.material || bodyA.material;
          var matB = shapeB.material || bodyB.material;
          if (matA && matB && matA.friction >= 0 && matB.friction >= 0) {
            friction = matA.friction * matB.friction;
          }
          if (friction > 0) {
            var mug = friction * world.gravity.length();
            var reducedMass = (bodyA.invMass + bodyB.invMass);
            if (reducedMass > 0) {
              reducedMass = 1 / reducedMass;
            }
            var pool = this.frictionEquationPool;
            var c1 = pool.length ? pool.pop() : new FrictionEquation(bodyA, bodyB, mug * reducedMass);
            var c2 = pool.length ? pool.pop() : new FrictionEquation(bodyA, bodyB, mug * reducedMass);
            c1.bi = c2.bi = bodyA;
            c1.bj = c2.bj = bodyB;
            c1.minForce = c2.minForce = -mug * reducedMass;
            c1.maxForce = c2.maxForce = mug * reducedMass;
            c1.ri.copy(contactEquation.ri);
            c1.rj.copy(contactEquation.rj);
            c2.ri.copy(contactEquation.ri);
            c2.rj.copy(contactEquation.rj);
            contactEquation.ni.tangents(c1.t, c2.t);
            c1.setSpookParams(cm.frictionEquationStiffness, cm.frictionEquationRelaxation, world.dt);
            c2.setSpookParams(cm.frictionEquationStiffness, cm.frictionEquationRelaxation, world.dt);
            c1.enabled = c2.enabled = contactEquation.enabled;
            outArray.push(c1, c2);
            return true;
          }
          return false;
        };
        var averageNormal = new Vec3();
        var averageContactPointA = new Vec3();
        var averageContactPointB = new Vec3();
        Narrowphase.prototype.createFrictionFromAverage = function(numContacts) {
          var c = this.result[this.result.length - 1];
          if (!this.createFrictionEquationsFromContact(c, this.frictionResult) || numContacts === 1) {
            return;
          }
          var f1 = this.frictionResult[this.frictionResult.length - 2];
          var f2 = this.frictionResult[this.frictionResult.length - 1];
          averageNormal.setZero();
          averageContactPointA.setZero();
          averageContactPointB.setZero();
          var bodyA = c.bi;
          var bodyB = c.bj;
          for (var i = 0; i !== numContacts; i++) {
            c = this.result[this.result.length - 1 - i];
            if (c.bodyA !== bodyA) {
              averageNormal.vadd(c.ni, averageNormal);
              averageContactPointA.vadd(c.ri, averageContactPointA);
              averageContactPointB.vadd(c.rj, averageContactPointB);
            } else {
              averageNormal.vsub(c.ni, averageNormal);
              averageContactPointA.vadd(c.rj, averageContactPointA);
              averageContactPointB.vadd(c.ri, averageContactPointB);
            }
          }
          var invNumContacts = 1 / numContacts;
          averageContactPointA.scale(invNumContacts, f1.ri);
          averageContactPointB.scale(invNumContacts, f1.rj);
          f2.ri.copy(f1.ri);
          f2.rj.copy(f1.rj);
          averageNormal.normalize();
          averageNormal.tangents(f1.t, f2.t);
        };
        var tmpVec1 = new Vec3();
        var tmpVec2 = new Vec3();
        var tmpQuat1 = new Quaternion();
        var tmpQuat2 = new Quaternion();
        Narrowphase.prototype.getContacts = function(p1, p2, world, result, oldcontacts, frictionResult, frictionPool) {
          this.contactPointPool = oldcontacts;
          this.frictionEquationPool = frictionPool;
          this.result = result;
          this.frictionResult = frictionResult;
          var qi = tmpQuat1;
          var qj = tmpQuat2;
          var xi = tmpVec1;
          var xj = tmpVec2;
          for (var k = 0,
              N = p1.length; k !== N; k++) {
            var bi = p1[k],
                bj = p2[k];
            var bodyContactMaterial = null;
            if (bi.material && bj.material) {
              bodyContactMaterial = world.getContactMaterial(bi.material, bj.material) || null;
            }
            for (var i = 0; i < bi.shapes.length; i++) {
              bi.quaternion.mult(bi.shapeOrientations[i], qi);
              bi.quaternion.vmult(bi.shapeOffsets[i], xi);
              xi.vadd(bi.position, xi);
              var si = bi.shapes[i];
              for (var j = 0; j < bj.shapes.length; j++) {
                bj.quaternion.mult(bj.shapeOrientations[j], qj);
                bj.quaternion.vmult(bj.shapeOffsets[j], xj);
                xj.vadd(bj.position, xj);
                var sj = bj.shapes[j];
                if (xi.distanceTo(xj) > si.boundingSphereRadius + sj.boundingSphereRadius) {
                  continue;
                }
                var shapeContactMaterial = null;
                if (si.material && sj.material) {
                  shapeContactMaterial = world.getContactMaterial(si.material, sj.material) || null;
                }
                this.currentContactMaterial = shapeContactMaterial || bodyContactMaterial || world.defaultContactMaterial;
                var resolver = this[si.type | sj.type];
                if (resolver) {
                  if (si.type < sj.type) {
                    resolver.call(this, si, sj, xi, xj, qi, qj, bi, bj, si, sj);
                  } else {
                    resolver.call(this, sj, si, xj, xi, qj, qi, bj, bi, si, sj);
                  }
                }
              }
            }
          }
        };
        var numWarnings = 0;
        var maxWarnings = 10;
        function warn(msg) {
          if (numWarnings > maxWarnings) {
            return;
          }
          numWarnings++;
          console.warn(msg);
        }
        Narrowphase.prototype[Shape.types.BOX | Shape.types.BOX] = Narrowphase.prototype.boxBox = function(si, sj, xi, xj, qi, qj, bi, bj) {
          si.convexPolyhedronRepresentation.material = si.material;
          sj.convexPolyhedronRepresentation.material = sj.material;
          si.convexPolyhedronRepresentation.collisionResponse = si.collisionResponse;
          sj.convexPolyhedronRepresentation.collisionResponse = sj.collisionResponse;
          this.convexConvex(si.convexPolyhedronRepresentation, sj.convexPolyhedronRepresentation, xi, xj, qi, qj, bi, bj, si, sj);
        };
        Narrowphase.prototype[Shape.types.BOX | Shape.types.CONVEXPOLYHEDRON] = Narrowphase.prototype.boxConvex = function(si, sj, xi, xj, qi, qj, bi, bj) {
          si.convexPolyhedronRepresentation.material = si.material;
          si.convexPolyhedronRepresentation.collisionResponse = si.collisionResponse;
          this.convexConvex(si.convexPolyhedronRepresentation, sj, xi, xj, qi, qj, bi, bj, si, sj);
        };
        Narrowphase.prototype[Shape.types.BOX | Shape.types.PARTICLE] = Narrowphase.prototype.boxParticle = function(si, sj, xi, xj, qi, qj, bi, bj) {
          si.convexPolyhedronRepresentation.material = si.material;
          si.convexPolyhedronRepresentation.collisionResponse = si.collisionResponse;
          this.convexParticle(si.convexPolyhedronRepresentation, sj, xi, xj, qi, qj, bi, bj, si, sj);
        };
        Narrowphase.prototype[Shape.types.SPHERE] = Narrowphase.prototype.sphereSphere = function(si, sj, xi, xj, qi, qj, bi, bj) {
          var r = this.createContactEquation(bi, bj, si, sj);
          xj.vsub(xi, r.ni);
          r.ni.normalize();
          r.ri.copy(r.ni);
          r.rj.copy(r.ni);
          r.ri.mult(si.radius, r.ri);
          r.rj.mult(-sj.radius, r.rj);
          r.ri.vadd(xi, r.ri);
          r.ri.vsub(bi.position, r.ri);
          r.rj.vadd(xj, r.rj);
          r.rj.vsub(bj.position, r.rj);
          this.result.push(r);
          this.createFrictionEquationsFromContact(r, this.frictionResult);
        };
        var planeTrimesh_normal = new Vec3();
        var planeTrimesh_relpos = new Vec3();
        var planeTrimesh_projected = new Vec3();
        Narrowphase.prototype[Shape.types.PLANE | Shape.types.TRIMESH] = Narrowphase.prototype.planeTrimesh = function(planeShape, trimeshShape, planePos, trimeshPos, planeQuat, trimeshQuat, planeBody, trimeshBody) {
          var v = new Vec3();
          var normal = planeTrimesh_normal;
          normal.set(0, 0, 1);
          planeQuat.vmult(normal, normal);
          for (var i = 0; i < trimeshShape.vertices.length / 3; i++) {
            trimeshShape.getVertex(i, v);
            var v2 = new Vec3();
            v2.copy(v);
            Transform.pointToWorldFrame(trimeshPos, trimeshQuat, v2, v);
            var relpos = planeTrimesh_relpos;
            v.vsub(planePos, relpos);
            var dot = normal.dot(relpos);
            if (dot <= 0.0) {
              var r = this.createContactEquation(planeBody, trimeshBody, planeShape, trimeshShape);
              r.ni.copy(normal);
              var projected = planeTrimesh_projected;
              normal.scale(relpos.dot(normal), projected);
              v.vsub(projected, projected);
              r.ri.copy(projected);
              r.ri.vsub(planeBody.position, r.ri);
              r.rj.copy(v);
              r.rj.vsub(trimeshBody.position, r.rj);
              this.result.push(r);
              this.createFrictionEquationsFromContact(r, this.frictionResult);
            }
          }
        };
        var sphereTrimesh_normal = new Vec3();
        var sphereTrimesh_relpos = new Vec3();
        var sphereTrimesh_projected = new Vec3();
        var sphereTrimesh_v = new Vec3();
        var sphereTrimesh_v2 = new Vec3();
        var sphereTrimesh_edgeVertexA = new Vec3();
        var sphereTrimesh_edgeVertexB = new Vec3();
        var sphereTrimesh_edgeVector = new Vec3();
        var sphereTrimesh_edgeVectorUnit = new Vec3();
        var sphereTrimesh_localSpherePos = new Vec3();
        var sphereTrimesh_tmp = new Vec3();
        var sphereTrimesh_va = new Vec3();
        var sphereTrimesh_vb = new Vec3();
        var sphereTrimesh_vc = new Vec3();
        var sphereTrimesh_localSphereAABB = new AABB();
        var sphereTrimesh_triangles = [];
        Narrowphase.prototype[Shape.types.SPHERE | Shape.types.TRIMESH] = Narrowphase.prototype.sphereTrimesh = function(sphereShape, trimeshShape, spherePos, trimeshPos, sphereQuat, trimeshQuat, sphereBody, trimeshBody) {
          var edgeVertexA = sphereTrimesh_edgeVertexA;
          var edgeVertexB = sphereTrimesh_edgeVertexB;
          var edgeVector = sphereTrimesh_edgeVector;
          var edgeVectorUnit = sphereTrimesh_edgeVectorUnit;
          var localSpherePos = sphereTrimesh_localSpherePos;
          var tmp = sphereTrimesh_tmp;
          var localSphereAABB = sphereTrimesh_localSphereAABB;
          var v2 = sphereTrimesh_v2;
          var relpos = sphereTrimesh_relpos;
          var triangles = sphereTrimesh_triangles;
          Transform.pointToLocalFrame(trimeshPos, trimeshQuat, spherePos, localSpherePos);
          var sphereRadius = sphereShape.radius;
          localSphereAABB.lowerBound.set(localSpherePos.x - sphereRadius, localSpherePos.y - sphereRadius, localSpherePos.z - sphereRadius);
          localSphereAABB.upperBound.set(localSpherePos.x + sphereRadius, localSpherePos.y + sphereRadius, localSpherePos.z + sphereRadius);
          trimeshShape.getTrianglesInAABB(localSphereAABB, triangles);
          var v = sphereTrimesh_v;
          var radiusSquared = sphereShape.radius * sphereShape.radius;
          for (var i = 0; i < triangles.length; i++) {
            for (var j = 0; j < 3; j++) {
              trimeshShape.getVertex(trimeshShape.indices[triangles[i] * 3 + j], v);
              v.vsub(localSpherePos, relpos);
              if (relpos.norm2() <= radiusSquared) {
                v2.copy(v);
                Transform.pointToWorldFrame(trimeshPos, trimeshQuat, v2, v);
                v.vsub(spherePos, relpos);
                var r = this.createContactEquation(sphereBody, trimeshBody, sphereShape, trimeshShape);
                r.ni.copy(relpos);
                r.ni.normalize();
                r.ri.copy(r.ni);
                r.ri.scale(sphereShape.radius, r.ri);
                r.ri.vadd(spherePos, r.ri);
                r.ri.vsub(sphereBody.position, r.ri);
                r.rj.copy(v);
                r.rj.vsub(trimeshBody.position, r.rj);
                this.result.push(r);
                this.createFrictionEquationsFromContact(r, this.frictionResult);
              }
            }
          }
          for (var i = 0; i < triangles.length; i++) {
            for (var j = 0; j < 3; j++) {
              trimeshShape.getVertex(trimeshShape.indices[triangles[i] * 3 + j], edgeVertexA);
              trimeshShape.getVertex(trimeshShape.indices[triangles[i] * 3 + ((j + 1) % 3)], edgeVertexB);
              edgeVertexB.vsub(edgeVertexA, edgeVector);
              localSpherePos.vsub(edgeVertexB, tmp);
              var positionAlongEdgeB = tmp.dot(edgeVector);
              localSpherePos.vsub(edgeVertexA, tmp);
              var positionAlongEdgeA = tmp.dot(edgeVector);
              if (positionAlongEdgeA > 0 && positionAlongEdgeB < 0) {
                localSpherePos.vsub(edgeVertexA, tmp);
                edgeVectorUnit.copy(edgeVector);
                edgeVectorUnit.normalize();
                positionAlongEdgeA = tmp.dot(edgeVectorUnit);
                edgeVectorUnit.scale(positionAlongEdgeA, tmp);
                tmp.vadd(edgeVertexA, tmp);
                var dist = tmp.distanceTo(localSpherePos);
                if (dist < sphereShape.radius) {
                  var r = this.createContactEquation(sphereBody, trimeshBody, sphereShape, trimeshShape);
                  tmp.vsub(localSpherePos, r.ni);
                  r.ni.normalize();
                  r.ni.scale(sphereShape.radius, r.ri);
                  Transform.pointToWorldFrame(trimeshPos, trimeshQuat, tmp, tmp);
                  tmp.vsub(trimeshBody.position, r.rj);
                  Transform.vectorToWorldFrame(trimeshQuat, r.ni, r.ni);
                  Transform.vectorToWorldFrame(trimeshQuat, r.ri, r.ri);
                  this.result.push(r);
                  this.createFrictionEquationsFromContact(r, this.frictionResult);
                }
              }
            }
          }
          var va = sphereTrimesh_va;
          var vb = sphereTrimesh_vb;
          var vc = sphereTrimesh_vc;
          var normal = sphereTrimesh_normal;
          for (var i = 0,
              N = triangles.length; i !== N; i++) {
            trimeshShape.getTriangleVertices(triangles[i], va, vb, vc);
            trimeshShape.getNormal(triangles[i], normal);
            localSpherePos.vsub(va, tmp);
            var dist = tmp.dot(normal);
            normal.scale(dist, tmp);
            localSpherePos.vsub(tmp, tmp);
            dist = tmp.distanceTo(localSpherePos);
            if (Ray.pointInTriangle(tmp, va, vb, vc) && dist < sphereShape.radius) {
              var r = this.createContactEquation(sphereBody, trimeshBody, sphereShape, trimeshShape);
              tmp.vsub(localSpherePos, r.ni);
              r.ni.normalize();
              r.ni.scale(sphereShape.radius, r.ri);
              Transform.pointToWorldFrame(trimeshPos, trimeshQuat, tmp, tmp);
              tmp.vsub(trimeshBody.position, r.rj);
              Transform.vectorToWorldFrame(trimeshQuat, r.ni, r.ni);
              Transform.vectorToWorldFrame(trimeshQuat, r.ri, r.ri);
              this.result.push(r);
              this.createFrictionEquationsFromContact(r, this.frictionResult);
            }
          }
          triangles.length = 0;
        };
        var point_on_plane_to_sphere = new Vec3();
        var plane_to_sphere_ortho = new Vec3();
        Narrowphase.prototype[Shape.types.SPHERE | Shape.types.PLANE] = Narrowphase.prototype.spherePlane = function(si, sj, xi, xj, qi, qj, bi, bj) {
          var r = this.createContactEquation(bi, bj, si, sj);
          r.ni.set(0, 0, 1);
          qj.vmult(r.ni, r.ni);
          r.ni.negate(r.ni);
          r.ni.normalize();
          r.ni.mult(si.radius, r.ri);
          xi.vsub(xj, point_on_plane_to_sphere);
          r.ni.mult(r.ni.dot(point_on_plane_to_sphere), plane_to_sphere_ortho);
          point_on_plane_to_sphere.vsub(plane_to_sphere_ortho, r.rj);
          if (-point_on_plane_to_sphere.dot(r.ni) <= si.radius) {
            var ri = r.ri;
            var rj = r.rj;
            ri.vadd(xi, ri);
            ri.vsub(bi.position, ri);
            rj.vadd(xj, rj);
            rj.vsub(bj.position, rj);
            this.result.push(r);
            this.createFrictionEquationsFromContact(r, this.frictionResult);
          }
        };
        var pointInPolygon_edge = new Vec3();
        var pointInPolygon_edge_x_normal = new Vec3();
        var pointInPolygon_vtp = new Vec3();
        function pointInPolygon(verts, normal, p) {
          var positiveResult = null;
          var N = verts.length;
          for (var i = 0; i !== N; i++) {
            var v = verts[i];
            var edge = pointInPolygon_edge;
            verts[(i + 1) % (N)].vsub(v, edge);
            var edge_x_normal = pointInPolygon_edge_x_normal;
            edge.cross(normal, edge_x_normal);
            var vertex_to_p = pointInPolygon_vtp;
            p.vsub(v, vertex_to_p);
            var r = edge_x_normal.dot(vertex_to_p);
            if (positiveResult === null || (r > 0 && positiveResult === true) || (r <= 0 && positiveResult === false)) {
              if (positiveResult === null) {
                positiveResult = r > 0;
              }
              continue;
            } else {
              return false;
            }
          }
          return true;
        }
        var box_to_sphere = new Vec3();
        var sphereBox_ns = new Vec3();
        var sphereBox_ns1 = new Vec3();
        var sphereBox_ns2 = new Vec3();
        var sphereBox_sides = [new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3()];
        var sphereBox_sphere_to_corner = new Vec3();
        var sphereBox_side_ns = new Vec3();
        var sphereBox_side_ns1 = new Vec3();
        var sphereBox_side_ns2 = new Vec3();
        Narrowphase.prototype[Shape.types.SPHERE | Shape.types.BOX] = Narrowphase.prototype.sphereBox = function(si, sj, xi, xj, qi, qj, bi, bj) {
          var v3pool = this.v3pool;
          var sides = sphereBox_sides;
          xi.vsub(xj, box_to_sphere);
          sj.getSideNormals(sides, qj);
          var R = si.radius;
          var penetrating_sides = [];
          var found = false;
          var side_ns = sphereBox_side_ns;
          var side_ns1 = sphereBox_side_ns1;
          var side_ns2 = sphereBox_side_ns2;
          var side_h = null;
          var side_penetrations = 0;
          var side_dot1 = 0;
          var side_dot2 = 0;
          var side_distance = null;
          for (var idx = 0,
              nsides = sides.length; idx !== nsides && found === false; idx++) {
            var ns = sphereBox_ns;
            ns.copy(sides[idx]);
            var h = ns.norm();
            ns.normalize();
            var dot = box_to_sphere.dot(ns);
            if (dot < h + R && dot > 0) {
              var ns1 = sphereBox_ns1;
              var ns2 = sphereBox_ns2;
              ns1.copy(sides[(idx + 1) % 3]);
              ns2.copy(sides[(idx + 2) % 3]);
              var h1 = ns1.norm();
              var h2 = ns2.norm();
              ns1.normalize();
              ns2.normalize();
              var dot1 = box_to_sphere.dot(ns1);
              var dot2 = box_to_sphere.dot(ns2);
              if (dot1 < h1 && dot1 > -h1 && dot2 < h2 && dot2 > -h2) {
                var dist = Math.abs(dot - h - R);
                if (side_distance === null || dist < side_distance) {
                  side_distance = dist;
                  side_dot1 = dot1;
                  side_dot2 = dot2;
                  side_h = h;
                  side_ns.copy(ns);
                  side_ns1.copy(ns1);
                  side_ns2.copy(ns2);
                  side_penetrations++;
                }
              }
            }
          }
          if (side_penetrations) {
            found = true;
            var r = this.createContactEquation(bi, bj, si, sj);
            side_ns.mult(-R, r.ri);
            r.ni.copy(side_ns);
            r.ni.negate(r.ni);
            side_ns.mult(side_h, side_ns);
            side_ns1.mult(side_dot1, side_ns1);
            side_ns.vadd(side_ns1, side_ns);
            side_ns2.mult(side_dot2, side_ns2);
            side_ns.vadd(side_ns2, r.rj);
            r.ri.vadd(xi, r.ri);
            r.ri.vsub(bi.position, r.ri);
            r.rj.vadd(xj, r.rj);
            r.rj.vsub(bj.position, r.rj);
            this.result.push(r);
            this.createFrictionEquationsFromContact(r, this.frictionResult);
          }
          var rj = v3pool.get();
          var sphere_to_corner = sphereBox_sphere_to_corner;
          for (var j = 0; j !== 2 && !found; j++) {
            for (var k = 0; k !== 2 && !found; k++) {
              for (var l = 0; l !== 2 && !found; l++) {
                rj.set(0, 0, 0);
                if (j) {
                  rj.vadd(sides[0], rj);
                } else {
                  rj.vsub(sides[0], rj);
                }
                if (k) {
                  rj.vadd(sides[1], rj);
                } else {
                  rj.vsub(sides[1], rj);
                }
                if (l) {
                  rj.vadd(sides[2], rj);
                } else {
                  rj.vsub(sides[2], rj);
                }
                xj.vadd(rj, sphere_to_corner);
                sphere_to_corner.vsub(xi, sphere_to_corner);
                if (sphere_to_corner.norm2() < R * R) {
                  found = true;
                  var r = this.createContactEquation(bi, bj, si, sj);
                  r.ri.copy(sphere_to_corner);
                  r.ri.normalize();
                  r.ni.copy(r.ri);
                  r.ri.mult(R, r.ri);
                  r.rj.copy(rj);
                  r.ri.vadd(xi, r.ri);
                  r.ri.vsub(bi.position, r.ri);
                  r.rj.vadd(xj, r.rj);
                  r.rj.vsub(bj.position, r.rj);
                  this.result.push(r);
                  this.createFrictionEquationsFromContact(r, this.frictionResult);
                }
              }
            }
          }
          v3pool.release(rj);
          rj = null;
          var edgeTangent = v3pool.get();
          var edgeCenter = v3pool.get();
          var r = v3pool.get();
          var orthogonal = v3pool.get();
          var dist = v3pool.get();
          var Nsides = sides.length;
          for (var j = 0; j !== Nsides && !found; j++) {
            for (var k = 0; k !== Nsides && !found; k++) {
              if (j % 3 !== k % 3) {
                sides[k].cross(sides[j], edgeTangent);
                edgeTangent.normalize();
                sides[j].vadd(sides[k], edgeCenter);
                r.copy(xi);
                r.vsub(edgeCenter, r);
                r.vsub(xj, r);
                var orthonorm = r.dot(edgeTangent);
                edgeTangent.mult(orthonorm, orthogonal);
                var l = 0;
                while (l === j % 3 || l === k % 3) {
                  l++;
                }
                dist.copy(xi);
                dist.vsub(orthogonal, dist);
                dist.vsub(edgeCenter, dist);
                dist.vsub(xj, dist);
                var tdist = Math.abs(orthonorm);
                var ndist = dist.norm();
                if (tdist < sides[l].norm() && ndist < R) {
                  found = true;
                  var res = this.createContactEquation(bi, bj, si, sj);
                  edgeCenter.vadd(orthogonal, res.rj);
                  res.rj.copy(res.rj);
                  dist.negate(res.ni);
                  res.ni.normalize();
                  res.ri.copy(res.rj);
                  res.ri.vadd(xj, res.ri);
                  res.ri.vsub(xi, res.ri);
                  res.ri.normalize();
                  res.ri.mult(R, res.ri);
                  res.ri.vadd(xi, res.ri);
                  res.ri.vsub(bi.position, res.ri);
                  res.rj.vadd(xj, res.rj);
                  res.rj.vsub(bj.position, res.rj);
                  this.result.push(res);
                  this.createFrictionEquationsFromContact(res, this.frictionResult);
                }
              }
            }
          }
          v3pool.release(edgeTangent, edgeCenter, r, orthogonal, dist);
        };
        var convex_to_sphere = new Vec3();
        var sphereConvex_edge = new Vec3();
        var sphereConvex_edgeUnit = new Vec3();
        var sphereConvex_sphereToCorner = new Vec3();
        var sphereConvex_worldCorner = new Vec3();
        var sphereConvex_worldNormal = new Vec3();
        var sphereConvex_worldPoint = new Vec3();
        var sphereConvex_worldSpherePointClosestToPlane = new Vec3();
        var sphereConvex_penetrationVec = new Vec3();
        var sphereConvex_sphereToWorldPoint = new Vec3();
        Narrowphase.prototype[Shape.types.SPHERE | Shape.types.CONVEXPOLYHEDRON] = Narrowphase.prototype.sphereConvex = function(si, sj, xi, xj, qi, qj, bi, bj) {
          var v3pool = this.v3pool;
          xi.vsub(xj, convex_to_sphere);
          var normals = sj.faceNormals;
          var faces = sj.faces;
          var verts = sj.vertices;
          var R = si.radius;
          var penetrating_sides = [];
          for (var i = 0; i !== verts.length; i++) {
            var v = verts[i];
            var worldCorner = sphereConvex_worldCorner;
            qj.vmult(v, worldCorner);
            xj.vadd(worldCorner, worldCorner);
            var sphere_to_corner = sphereConvex_sphereToCorner;
            worldCorner.vsub(xi, sphere_to_corner);
            if (sphere_to_corner.norm2() < R * R) {
              found = true;
              var r = this.createContactEquation(bi, bj, si, sj);
              r.ri.copy(sphere_to_corner);
              r.ri.normalize();
              r.ni.copy(r.ri);
              r.ri.mult(R, r.ri);
              worldCorner.vsub(xj, r.rj);
              r.ri.vadd(xi, r.ri);
              r.ri.vsub(bi.position, r.ri);
              r.rj.vadd(xj, r.rj);
              r.rj.vsub(bj.position, r.rj);
              this.result.push(r);
              this.createFrictionEquationsFromContact(r, this.frictionResult);
              return;
            }
          }
          var found = false;
          for (var i = 0,
              nfaces = faces.length; i !== nfaces && found === false; i++) {
            var normal = normals[i];
            var face = faces[i];
            var worldNormal = sphereConvex_worldNormal;
            qj.vmult(normal, worldNormal);
            var worldPoint = sphereConvex_worldPoint;
            qj.vmult(verts[face[0]], worldPoint);
            worldPoint.vadd(xj, worldPoint);
            var worldSpherePointClosestToPlane = sphereConvex_worldSpherePointClosestToPlane;
            worldNormal.mult(-R, worldSpherePointClosestToPlane);
            xi.vadd(worldSpherePointClosestToPlane, worldSpherePointClosestToPlane);
            var penetrationVec = sphereConvex_penetrationVec;
            worldSpherePointClosestToPlane.vsub(worldPoint, penetrationVec);
            var penetration = penetrationVec.dot(worldNormal);
            var worldPointToSphere = sphereConvex_sphereToWorldPoint;
            xi.vsub(worldPoint, worldPointToSphere);
            if (penetration < 0 && worldPointToSphere.dot(worldNormal) > 0) {
              var faceVerts = [];
              for (var j = 0,
                  Nverts = face.length; j !== Nverts; j++) {
                var worldVertex = v3pool.get();
                qj.vmult(verts[face[j]], worldVertex);
                xj.vadd(worldVertex, worldVertex);
                faceVerts.push(worldVertex);
              }
              if (pointInPolygon(faceVerts, worldNormal, xi)) {
                found = true;
                var r = this.createContactEquation(bi, bj, si, sj);
                worldNormal.mult(-R, r.ri);
                worldNormal.negate(r.ni);
                var penetrationVec2 = v3pool.get();
                worldNormal.mult(-penetration, penetrationVec2);
                var penetrationSpherePoint = v3pool.get();
                worldNormal.mult(-R, penetrationSpherePoint);
                xi.vsub(xj, r.rj);
                r.rj.vadd(penetrationSpherePoint, r.rj);
                r.rj.vadd(penetrationVec2, r.rj);
                r.rj.vadd(xj, r.rj);
                r.rj.vsub(bj.position, r.rj);
                r.ri.vadd(xi, r.ri);
                r.ri.vsub(bi.position, r.ri);
                v3pool.release(penetrationVec2);
                v3pool.release(penetrationSpherePoint);
                this.result.push(r);
                this.createFrictionEquationsFromContact(r, this.frictionResult);
                for (var j = 0,
                    Nfaceverts = faceVerts.length; j !== Nfaceverts; j++) {
                  v3pool.release(faceVerts[j]);
                }
                return;
              } else {
                for (var j = 0; j !== face.length; j++) {
                  var v1 = v3pool.get();
                  var v2 = v3pool.get();
                  qj.vmult(verts[face[(j + 1) % face.length]], v1);
                  qj.vmult(verts[face[(j + 2) % face.length]], v2);
                  xj.vadd(v1, v1);
                  xj.vadd(v2, v2);
                  var edge = sphereConvex_edge;
                  v2.vsub(v1, edge);
                  var edgeUnit = sphereConvex_edgeUnit;
                  edge.unit(edgeUnit);
                  var p = v3pool.get();
                  var v1_to_xi = v3pool.get();
                  xi.vsub(v1, v1_to_xi);
                  var dot = v1_to_xi.dot(edgeUnit);
                  edgeUnit.mult(dot, p);
                  p.vadd(v1, p);
                  var xi_to_p = v3pool.get();
                  p.vsub(xi, xi_to_p);
                  if (dot > 0 && dot * dot < edge.norm2() && xi_to_p.norm2() < R * R) {
                    var r = this.createContactEquation(bi, bj, si, sj);
                    p.vsub(xj, r.rj);
                    p.vsub(xi, r.ni);
                    r.ni.normalize();
                    r.ni.mult(R, r.ri);
                    r.rj.vadd(xj, r.rj);
                    r.rj.vsub(bj.position, r.rj);
                    r.ri.vadd(xi, r.ri);
                    r.ri.vsub(bi.position, r.ri);
                    this.result.push(r);
                    this.createFrictionEquationsFromContact(r, this.frictionResult);
                    for (var j = 0,
                        Nfaceverts = faceVerts.length; j !== Nfaceverts; j++) {
                      v3pool.release(faceVerts[j]);
                    }
                    v3pool.release(v1);
                    v3pool.release(v2);
                    v3pool.release(p);
                    v3pool.release(xi_to_p);
                    v3pool.release(v1_to_xi);
                    return;
                  }
                  v3pool.release(v1);
                  v3pool.release(v2);
                  v3pool.release(p);
                  v3pool.release(xi_to_p);
                  v3pool.release(v1_to_xi);
                }
              }
              for (var j = 0,
                  Nfaceverts = faceVerts.length; j !== Nfaceverts; j++) {
                v3pool.release(faceVerts[j]);
              }
            }
          }
        };
        var planeBox_normal = new Vec3();
        var plane_to_corner = new Vec3();
        Narrowphase.prototype[Shape.types.PLANE | Shape.types.BOX] = Narrowphase.prototype.planeBox = function(si, sj, xi, xj, qi, qj, bi, bj) {
          sj.convexPolyhedronRepresentation.material = sj.material;
          sj.convexPolyhedronRepresentation.collisionResponse = sj.collisionResponse;
          this.planeConvex(si, sj.convexPolyhedronRepresentation, xi, xj, qi, qj, bi, bj);
        };
        var planeConvex_v = new Vec3();
        var planeConvex_normal = new Vec3();
        var planeConvex_relpos = new Vec3();
        var planeConvex_projected = new Vec3();
        Narrowphase.prototype[Shape.types.PLANE | Shape.types.CONVEXPOLYHEDRON] = Narrowphase.prototype.planeConvex = function(planeShape, convexShape, planePosition, convexPosition, planeQuat, convexQuat, planeBody, convexBody) {
          var worldVertex = planeConvex_v,
              worldNormal = planeConvex_normal;
          worldNormal.set(0, 0, 1);
          planeQuat.vmult(worldNormal, worldNormal);
          var numContacts = 0;
          var relpos = planeConvex_relpos;
          for (var i = 0; i !== convexShape.vertices.length; i++) {
            worldVertex.copy(convexShape.vertices[i]);
            convexQuat.vmult(worldVertex, worldVertex);
            convexPosition.vadd(worldVertex, worldVertex);
            worldVertex.vsub(planePosition, relpos);
            var dot = worldNormal.dot(relpos);
            if (dot <= 0.0) {
              var r = this.createContactEquation(planeBody, convexBody, planeShape, convexShape);
              var projected = planeConvex_projected;
              worldNormal.mult(worldNormal.dot(relpos), projected);
              worldVertex.vsub(projected, projected);
              projected.vsub(planePosition, r.ri);
              r.ni.copy(worldNormal);
              worldVertex.vsub(convexPosition, r.rj);
              r.ri.vadd(planePosition, r.ri);
              r.ri.vsub(planeBody.position, r.ri);
              r.rj.vadd(convexPosition, r.rj);
              r.rj.vsub(convexBody.position, r.rj);
              this.result.push(r);
              numContacts++;
              if (!this.enableFrictionReduction) {
                this.createFrictionEquationsFromContact(r, this.frictionResult);
              }
            }
          }
          if (this.enableFrictionReduction && numContacts) {
            this.createFrictionFromAverage(numContacts);
          }
        };
        var convexConvex_sepAxis = new Vec3();
        var convexConvex_q = new Vec3();
        Narrowphase.prototype[Shape.types.CONVEXPOLYHEDRON] = Narrowphase.prototype.convexConvex = function(si, sj, xi, xj, qi, qj, bi, bj, rsi, rsj, faceListA, faceListB) {
          var sepAxis = convexConvex_sepAxis;
          if (xi.distanceTo(xj) > si.boundingSphereRadius + sj.boundingSphereRadius) {
            return;
          }
          if (si.findSeparatingAxis(sj, xi, qi, xj, qj, sepAxis, faceListA, faceListB)) {
            var res = [];
            var q = convexConvex_q;
            si.clipAgainstHull(xi, qi, sj, xj, qj, sepAxis, -100, 100, res);
            var numContacts = 0;
            for (var j = 0; j !== res.length; j++) {
              var r = this.createContactEquation(bi, bj, si, sj, rsi, rsj),
                  ri = r.ri,
                  rj = r.rj;
              sepAxis.negate(r.ni);
              res[j].normal.negate(q);
              q.mult(res[j].depth, q);
              res[j].point.vadd(q, ri);
              rj.copy(res[j].point);
              ri.vsub(xi, ri);
              rj.vsub(xj, rj);
              ri.vadd(xi, ri);
              ri.vsub(bi.position, ri);
              rj.vadd(xj, rj);
              rj.vsub(bj.position, rj);
              this.result.push(r);
              numContacts++;
              if (!this.enableFrictionReduction) {
                this.createFrictionEquationsFromContact(r, this.frictionResult);
              }
            }
            if (this.enableFrictionReduction && numContacts) {
              this.createFrictionFromAverage(numContacts);
            }
          }
        };
        var particlePlane_normal = new Vec3();
        var particlePlane_relpos = new Vec3();
        var particlePlane_projected = new Vec3();
        Narrowphase.prototype[Shape.types.PLANE | Shape.types.PARTICLE] = Narrowphase.prototype.planeParticle = function(sj, si, xj, xi, qj, qi, bj, bi) {
          var normal = particlePlane_normal;
          normal.set(0, 0, 1);
          bj.quaternion.vmult(normal, normal);
          var relpos = particlePlane_relpos;
          xi.vsub(bj.position, relpos);
          var dot = normal.dot(relpos);
          if (dot <= 0.0) {
            var r = this.createContactEquation(bi, bj, si, sj);
            r.ni.copy(normal);
            r.ni.negate(r.ni);
            r.ri.set(0, 0, 0);
            var projected = particlePlane_projected;
            normal.mult(normal.dot(xi), projected);
            xi.vsub(projected, projected);
            r.rj.copy(projected);
            this.result.push(r);
            this.createFrictionEquationsFromContact(r, this.frictionResult);
          }
        };
        var particleSphere_normal = new Vec3();
        Narrowphase.prototype[Shape.types.PARTICLE | Shape.types.SPHERE] = Narrowphase.prototype.sphereParticle = function(sj, si, xj, xi, qj, qi, bj, bi) {
          var normal = particleSphere_normal;
          normal.set(0, 0, 1);
          xi.vsub(xj, normal);
          var lengthSquared = normal.norm2();
          if (lengthSquared <= sj.radius * sj.radius) {
            var r = this.createContactEquation(bi, bj, si, sj);
            normal.normalize();
            r.rj.copy(normal);
            r.rj.mult(sj.radius, r.rj);
            r.ni.copy(normal);
            r.ni.negate(r.ni);
            r.ri.set(0, 0, 0);
            this.result.push(r);
            this.createFrictionEquationsFromContact(r, this.frictionResult);
          }
        };
        var cqj = new Quaternion();
        var convexParticle_local = new Vec3();
        var convexParticle_normal = new Vec3();
        var convexParticle_penetratedFaceNormal = new Vec3();
        var convexParticle_vertexToParticle = new Vec3();
        var convexParticle_worldPenetrationVec = new Vec3();
        Narrowphase.prototype[Shape.types.PARTICLE | Shape.types.CONVEXPOLYHEDRON] = Narrowphase.prototype.convexParticle = function(sj, si, xj, xi, qj, qi, bj, bi) {
          var penetratedFaceIndex = -1;
          var penetratedFaceNormal = convexParticle_penetratedFaceNormal;
          var worldPenetrationVec = convexParticle_worldPenetrationVec;
          var minPenetration = null;
          var numDetectedFaces = 0;
          var local = convexParticle_local;
          local.copy(xi);
          local.vsub(xj, local);
          qj.conjugate(cqj);
          cqj.vmult(local, local);
          if (sj.pointIsInside(local)) {
            if (sj.worldVerticesNeedsUpdate) {
              sj.computeWorldVertices(xj, qj);
            }
            if (sj.worldFaceNormalsNeedsUpdate) {
              sj.computeWorldFaceNormals(qj);
            }
            for (var i = 0,
                nfaces = sj.faces.length; i !== nfaces; i++) {
              var verts = [sj.worldVertices[sj.faces[i][0]]];
              var normal = sj.worldFaceNormals[i];
              xi.vsub(verts[0], convexParticle_vertexToParticle);
              var penetration = -normal.dot(convexParticle_vertexToParticle);
              if (minPenetration === null || Math.abs(penetration) < Math.abs(minPenetration)) {
                minPenetration = penetration;
                penetratedFaceIndex = i;
                penetratedFaceNormal.copy(normal);
                numDetectedFaces++;
              }
            }
            if (penetratedFaceIndex !== -1) {
              var r = this.createContactEquation(bi, bj, si, sj);
              penetratedFaceNormal.mult(minPenetration, worldPenetrationVec);
              worldPenetrationVec.vadd(xi, worldPenetrationVec);
              worldPenetrationVec.vsub(xj, worldPenetrationVec);
              r.rj.copy(worldPenetrationVec);
              penetratedFaceNormal.negate(r.ni);
              r.ri.set(0, 0, 0);
              var ri = r.ri,
                  rj = r.rj;
              ri.vadd(xi, ri);
              ri.vsub(bi.position, ri);
              rj.vadd(xj, rj);
              rj.vsub(bj.position, rj);
              this.result.push(r);
              this.createFrictionEquationsFromContact(r, this.frictionResult);
            } else {
              console.warn("Point found inside convex, but did not find penetrating face!");
            }
          }
        };
        Narrowphase.prototype[Shape.types.BOX | Shape.types.HEIGHTFIELD] = Narrowphase.prototype.boxHeightfield = function(si, sj, xi, xj, qi, qj, bi, bj) {
          si.convexPolyhedronRepresentation.material = si.material;
          si.convexPolyhedronRepresentation.collisionResponse = si.collisionResponse;
          this.convexHeightfield(si.convexPolyhedronRepresentation, sj, xi, xj, qi, qj, bi, bj);
        };
        var convexHeightfield_tmp1 = new Vec3();
        var convexHeightfield_tmp2 = new Vec3();
        var convexHeightfield_faceList = [0];
        Narrowphase.prototype[Shape.types.CONVEXPOLYHEDRON | Shape.types.HEIGHTFIELD] = Narrowphase.prototype.convexHeightfield = function(convexShape, hfShape, convexPos, hfPos, convexQuat, hfQuat, convexBody, hfBody) {
          var data = hfShape.data,
              w = hfShape.elementSize,
              radius = convexShape.boundingSphereRadius,
              worldPillarOffset = convexHeightfield_tmp2,
              faceList = convexHeightfield_faceList;
          var localConvexPos = convexHeightfield_tmp1;
          Transform.pointToLocalFrame(hfPos, hfQuat, convexPos, localConvexPos);
          var iMinX = Math.floor((localConvexPos.x - radius) / w) - 1,
              iMaxX = Math.ceil((localConvexPos.x + radius) / w) + 1,
              iMinY = Math.floor((localConvexPos.y - radius) / w) - 1,
              iMaxY = Math.ceil((localConvexPos.y + radius) / w) + 1;
          if (iMaxX < 0 || iMaxY < 0 || iMinX > data.length || iMinY > data[0].length) {
            return;
          }
          if (iMinX < 0) {
            iMinX = 0;
          }
          if (iMaxX < 0) {
            iMaxX = 0;
          }
          if (iMinY < 0) {
            iMinY = 0;
          }
          if (iMaxY < 0) {
            iMaxY = 0;
          }
          if (iMinX >= data.length) {
            iMinX = data.length - 1;
          }
          if (iMaxX >= data.length) {
            iMaxX = data.length - 1;
          }
          if (iMaxY >= data[0].length) {
            iMaxY = data[0].length - 1;
          }
          if (iMinY >= data[0].length) {
            iMinY = data[0].length - 1;
          }
          var minMax = [];
          hfShape.getRectMinMax(iMinX, iMinY, iMaxX, iMaxY, minMax);
          var min = minMax[0];
          var max = minMax[1];
          if (localConvexPos.z - radius > max || localConvexPos.z + radius < min) {
            return;
          }
          for (var i = iMinX; i < iMaxX; i++) {
            for (var j = iMinY; j < iMaxY; j++) {
              hfShape.getConvexTrianglePillar(i, j, false);
              Transform.pointToWorldFrame(hfPos, hfQuat, hfShape.pillarOffset, worldPillarOffset);
              if (convexPos.distanceTo(worldPillarOffset) < hfShape.pillarConvex.boundingSphereRadius + convexShape.boundingSphereRadius) {
                this.convexConvex(convexShape, hfShape.pillarConvex, convexPos, worldPillarOffset, convexQuat, hfQuat, convexBody, hfBody, null, null, faceList, null);
              }
              hfShape.getConvexTrianglePillar(i, j, true);
              Transform.pointToWorldFrame(hfPos, hfQuat, hfShape.pillarOffset, worldPillarOffset);
              if (convexPos.distanceTo(worldPillarOffset) < hfShape.pillarConvex.boundingSphereRadius + convexShape.boundingSphereRadius) {
                this.convexConvex(convexShape, hfShape.pillarConvex, convexPos, worldPillarOffset, convexQuat, hfQuat, convexBody, hfBody, null, null, faceList, null);
              }
            }
          }
        };
        var sphereHeightfield_tmp1 = new Vec3();
        var sphereHeightfield_tmp2 = new Vec3();
        Narrowphase.prototype[Shape.types.SPHERE | Shape.types.HEIGHTFIELD] = Narrowphase.prototype.sphereHeightfield = function(sphereShape, hfShape, spherePos, hfPos, sphereQuat, hfQuat, sphereBody, hfBody) {
          var data = hfShape.data,
              radius = sphereShape.radius,
              w = hfShape.elementSize,
              worldPillarOffset = sphereHeightfield_tmp2;
          var localSpherePos = sphereHeightfield_tmp1;
          Transform.pointToLocalFrame(hfPos, hfQuat, spherePos, localSpherePos);
          var iMinX = Math.floor((localSpherePos.x - radius) / w) - 1,
              iMaxX = Math.ceil((localSpherePos.x + radius) / w) + 1,
              iMinY = Math.floor((localSpherePos.y - radius) / w) - 1,
              iMaxY = Math.ceil((localSpherePos.y + radius) / w) + 1;
          if (iMaxX < 0 || iMaxY < 0 || iMinX > data.length || iMaxY > data[0].length) {
            return;
          }
          if (iMinX < 0) {
            iMinX = 0;
          }
          if (iMaxX < 0) {
            iMaxX = 0;
          }
          if (iMinY < 0) {
            iMinY = 0;
          }
          if (iMaxY < 0) {
            iMaxY = 0;
          }
          if (iMinX >= data.length) {
            iMinX = data.length - 1;
          }
          if (iMaxX >= data.length) {
            iMaxX = data.length - 1;
          }
          if (iMaxY >= data[0].length) {
            iMaxY = data[0].length - 1;
          }
          if (iMinY >= data[0].length) {
            iMinY = data[0].length - 1;
          }
          var minMax = [];
          hfShape.getRectMinMax(iMinX, iMinY, iMaxX, iMaxY, minMax);
          var min = minMax[0];
          var max = minMax[1];
          if (localSpherePos.z - radius > max || localSpherePos.z + radius < min) {
            return;
          }
          var result = this.result;
          for (var i = iMinX; i < iMaxX; i++) {
            for (var j = iMinY; j < iMaxY; j++) {
              var numContactsBefore = result.length;
              hfShape.getConvexTrianglePillar(i, j, false);
              Transform.pointToWorldFrame(hfPos, hfQuat, hfShape.pillarOffset, worldPillarOffset);
              if (spherePos.distanceTo(worldPillarOffset) < hfShape.pillarConvex.boundingSphereRadius + sphereShape.boundingSphereRadius) {
                this.sphereConvex(sphereShape, hfShape.pillarConvex, spherePos, worldPillarOffset, sphereQuat, hfQuat, sphereBody, hfBody);
              }
              hfShape.getConvexTrianglePillar(i, j, true);
              Transform.pointToWorldFrame(hfPos, hfQuat, hfShape.pillarOffset, worldPillarOffset);
              if (spherePos.distanceTo(worldPillarOffset) < hfShape.pillarConvex.boundingSphereRadius + sphereShape.boundingSphereRadius) {
                this.sphereConvex(sphereShape, hfShape.pillarConvex, spherePos, worldPillarOffset, sphereQuat, hfQuat, sphereBody, hfBody);
              }
              var numContacts = result.length - numContactsBefore;
              if (numContacts > 2) {
                return;
              }
            }
          }
        };
      }, {
        "../collision/AABB": 3,
        "../collision/Ray": 9,
        "../equations/ContactEquation": 19,
        "../equations/FrictionEquation": 21,
        "../math/Quaternion": 28,
        "../math/Transform": 29,
        "../math/Vec3": 30,
        "../shapes/ConvexPolyhedron": 38,
        "../shapes/Shape": 43,
        "../solver/Solver": 47,
        "../utils/Vec3Pool": 54
      }],
      56: [function(_dereq_, module, exports) {
        module.exports = World;
        var Shape = _dereq_('../shapes/Shape');
        var Vec3 = _dereq_('../math/Vec3');
        var Quaternion = _dereq_('../math/Quaternion');
        var GSSolver = _dereq_('../solver/GSSolver');
        var Vec3Pool = _dereq_('../utils/Vec3Pool');
        var ContactEquation = _dereq_('../equations/ContactEquation');
        var FrictionEquation = _dereq_('../equations/FrictionEquation');
        var Narrowphase = _dereq_('./Narrowphase');
        var EventTarget = _dereq_('../utils/EventTarget');
        var ArrayCollisionMatrix = _dereq_('../collision/ArrayCollisionMatrix');
        var Material = _dereq_('../material/Material');
        var ContactMaterial = _dereq_('../material/ContactMaterial');
        var Body = _dereq_('../objects/Body');
        var TupleDictionary = _dereq_('../utils/TupleDictionary');
        var RaycastResult = _dereq_('../collision/RaycastResult');
        var AABB = _dereq_('../collision/AABB');
        var Ray = _dereq_('../collision/Ray');
        var NaiveBroadphase = _dereq_('../collision/NaiveBroadphase');
        function World() {
          EventTarget.apply(this);
          this.dt = -1;
          this.allowSleep = false;
          this.contacts = [];
          this.frictionEquations = [];
          this.quatNormalizeSkip = 0;
          this.quatNormalizeFast = false;
          this.time = 0.0;
          this.stepnumber = 0;
          this.default_dt = 1 / 60;
          this.nextId = 0;
          this.gravity = new Vec3();
          this.broadphase = new NaiveBroadphase();
          this.bodies = [];
          this.solver = new GSSolver();
          this.constraints = [];
          this.narrowphase = new Narrowphase(this);
          this.collisionMatrix = new ArrayCollisionMatrix();
          this.collisionMatrixPrevious = new ArrayCollisionMatrix();
          this.materials = [];
          this.contactmaterials = [];
          this.contactMaterialTable = new TupleDictionary();
          this.defaultMaterial = new Material("default");
          this.defaultContactMaterial = new ContactMaterial(this.defaultMaterial, this.defaultMaterial, {
            friction: 0.3,
            restitution: 0.0
          });
          this.doProfiling = false;
          this.profile = {
            solve: 0,
            makeContactConstraints: 0,
            broadphase: 0,
            integrate: 0,
            narrowphase: 0
          };
          this.subsystems = [];
          this.addBodyEvent = {
            type: "addBody",
            body: null
          };
          this.removeBodyEvent = {
            type: "removeBody",
            body: null
          };
        }
        World.prototype = new EventTarget();
        var tmpAABB1 = new AABB();
        var tmpArray1 = [];
        var tmpRay = new Ray();
        World.prototype.getContactMaterial = function(m1, m2) {
          return this.contactMaterialTable.get(m1.id, m2.id);
        };
        World.prototype.numObjects = function() {
          return this.bodies.length;
        };
        World.prototype.collisionMatrixTick = function() {
          var temp = this.collisionMatrixPrevious;
          this.collisionMatrixPrevious = this.collisionMatrix;
          this.collisionMatrix = temp;
          this.collisionMatrix.reset();
        };
        World.prototype.add = World.prototype.addBody = function(body) {
          if (this.bodies.indexOf(body) !== -1) {
            return;
          }
          body.index = this.bodies.length;
          this.bodies.push(body);
          body.world = this;
          body.initPosition.copy(body.position);
          body.initVelocity.copy(body.velocity);
          body.timeLastSleepy = this.time;
          if (body instanceof Body) {
            body.initAngularVelocity.copy(body.angularVelocity);
            body.initQuaternion.copy(body.quaternion);
          }
          this.collisionMatrix.setNumObjects(this.bodies.length);
          this.addBodyEvent.body = body;
          this.dispatchEvent(this.addBodyEvent);
        };
        World.prototype.addConstraint = function(c) {
          this.constraints.push(c);
        };
        World.prototype.removeConstraint = function(c) {
          var idx = this.constraints.indexOf(c);
          if (idx !== -1) {
            this.constraints.splice(idx, 1);
          }
        };
        World.prototype.rayTest = function(from, to, result) {
          if (result instanceof RaycastResult) {
            this.raycastClosest(from, to, {skipBackfaces: true}, result);
          } else {
            this.raycastAll(from, to, {skipBackfaces: true}, result);
          }
        };
        World.prototype.raycastAll = function(from, to, options, callback) {
          options.mode = Ray.ALL;
          options.from = from;
          options.to = to;
          options.callback = callback;
          return tmpRay.intersectWorld(this, options);
        };
        World.prototype.raycastAny = function(from, to, options, result) {
          options.mode = Ray.ANY;
          options.from = from;
          options.to = to;
          options.result = result;
          return tmpRay.intersectWorld(this, options);
        };
        World.prototype.raycastClosest = function(from, to, options, result) {
          options.mode = Ray.CLOSEST;
          options.from = from;
          options.to = to;
          options.result = result;
          return tmpRay.intersectWorld(this, options);
        };
        World.prototype.remove = function(body) {
          body.world = null;
          var n = this.bodies.length - 1,
              bodies = this.bodies,
              idx = bodies.indexOf(body);
          if (idx !== -1) {
            bodies.splice(idx, 1);
            for (var i = 0; i !== bodies.length; i++) {
              bodies[i].index = i;
            }
            this.collisionMatrix.setNumObjects(n);
            this.removeBodyEvent.body = body;
            this.dispatchEvent(this.removeBodyEvent);
          }
        };
        World.prototype.removeBody = World.prototype.remove;
        World.prototype.addMaterial = function(m) {
          this.materials.push(m);
        };
        World.prototype.addContactMaterial = function(cmat) {
          this.contactmaterials.push(cmat);
          this.contactMaterialTable.set(cmat.materials[0].id, cmat.materials[1].id, cmat);
        };
        if (typeof performance === 'undefined') {
          performance = {};
        }
        if (!performance.now) {
          var nowOffset = Date.now();
          if (performance.timing && performance.timing.navigationStart) {
            nowOffset = performance.timing.navigationStart;
          }
          performance.now = function() {
            return Date.now() - nowOffset;
          };
        }
        var step_tmp1 = new Vec3();
        World.prototype.step = function(dt, timeSinceLastCalled, maxSubSteps) {
          maxSubSteps = maxSubSteps || 10;
          timeSinceLastCalled = timeSinceLastCalled || 0;
          if (timeSinceLastCalled === 0) {
            this.internalStep(dt);
            this.time += dt;
          } else {
            var internalSteps = Math.floor((this.time + timeSinceLastCalled) / dt) - Math.floor(this.time / dt);
            internalSteps = Math.min(internalSteps, maxSubSteps);
            var t0 = performance.now();
            for (var i = 0; i !== internalSteps; i++) {
              this.internalStep(dt);
              if (performance.now() - t0 > dt * 1000) {
                break;
              }
            }
            this.time += timeSinceLastCalled;
            var h = this.time % dt;
            var h_div_dt = h / dt;
            var interpvelo = step_tmp1;
            var bodies = this.bodies;
            for (var j = 0; j !== bodies.length; j++) {
              var b = bodies[j];
              if (b.type !== Body.STATIC && b.sleepState !== Body.SLEEPING) {
                b.position.vsub(b.previousPosition, interpvelo);
                interpvelo.scale(h_div_dt, interpvelo);
                b.position.vadd(interpvelo, b.interpolatedPosition);
              } else {
                b.interpolatedPosition.copy(b.position);
                b.interpolatedQuaternion.copy(b.quaternion);
              }
            }
          }
        };
        var World_step_postStepEvent = {type: "postStep"},
            World_step_preStepEvent = {type: "preStep"},
            World_step_collideEvent = {
              type: "collide",
              body: null,
              contact: null
            },
            World_step_oldContacts = [],
            World_step_frictionEquationPool = [],
            World_step_p1 = [],
            World_step_p2 = [],
            World_step_gvec = new Vec3(),
            World_step_vi = new Vec3(),
            World_step_vj = new Vec3(),
            World_step_wi = new Vec3(),
            World_step_wj = new Vec3(),
            World_step_t1 = new Vec3(),
            World_step_t2 = new Vec3(),
            World_step_rixn = new Vec3(),
            World_step_rjxn = new Vec3(),
            World_step_step_q = new Quaternion(),
            World_step_step_w = new Quaternion(),
            World_step_step_wq = new Quaternion(),
            invI_tau_dt = new Vec3();
        World.prototype.internalStep = function(dt) {
          this.dt = dt;
          var world = this,
              that = this,
              contacts = this.contacts,
              p1 = World_step_p1,
              p2 = World_step_p2,
              N = this.numObjects(),
              bodies = this.bodies,
              solver = this.solver,
              gravity = this.gravity,
              doProfiling = this.doProfiling,
              profile = this.profile,
              DYNAMIC = Body.DYNAMIC,
              profilingStart,
              constraints = this.constraints,
              frictionEquationPool = World_step_frictionEquationPool,
              gnorm = gravity.norm(),
              gx = gravity.x,
              gy = gravity.y,
              gz = gravity.z,
              i = 0;
          if (doProfiling) {
            profilingStart = performance.now();
          }
          for (i = 0; i !== N; i++) {
            var bi = bodies[i];
            if (bi.type & DYNAMIC) {
              var f = bi.force,
                  m = bi.mass;
              f.x += m * gx;
              f.y += m * gy;
              f.z += m * gz;
            }
          }
          for (var i = 0,
              Nsubsystems = this.subsystems.length; i !== Nsubsystems; i++) {
            this.subsystems[i].update();
          }
          if (doProfiling) {
            profilingStart = performance.now();
          }
          p1.length = 0;
          p2.length = 0;
          this.broadphase.collisionPairs(this, p1, p2);
          if (doProfiling) {
            profile.broadphase = performance.now() - profilingStart;
          }
          var Nconstraints = constraints.length;
          for (i = 0; i !== Nconstraints; i++) {
            var c = constraints[i];
            if (!c.collideConnected) {
              for (var j = p1.length - 1; j >= 0; j -= 1) {
                if ((c.bodyA === p1[j] && c.bodyB === p2[j]) || (c.bodyB === p1[j] && c.bodyA === p2[j])) {
                  p1.splice(j, 1);
                  p2.splice(j, 1);
                }
              }
            }
          }
          this.collisionMatrixTick();
          if (doProfiling) {
            profilingStart = performance.now();
          }
          var oldcontacts = World_step_oldContacts;
          var NoldContacts = contacts.length;
          for (i = 0; i !== NoldContacts; i++) {
            oldcontacts.push(contacts[i]);
          }
          contacts.length = 0;
          var NoldFrictionEquations = this.frictionEquations.length;
          for (i = 0; i !== NoldFrictionEquations; i++) {
            frictionEquationPool.push(this.frictionEquations[i]);
          }
          this.frictionEquations.length = 0;
          this.narrowphase.getContacts(p1, p2, this, contacts, oldcontacts, this.frictionEquations, frictionEquationPool);
          if (doProfiling) {
            profile.narrowphase = performance.now() - profilingStart;
          }
          if (doProfiling) {
            profilingStart = performance.now();
          }
          for (var i = 0; i < this.frictionEquations.length; i++) {
            solver.addEquation(this.frictionEquations[i]);
          }
          var ncontacts = contacts.length;
          for (var k = 0; k !== ncontacts; k++) {
            var c = contacts[k];
            var bi = c.bi,
                bj = c.bj,
                si = c.si,
                sj = c.sj;
            var cm;
            if (bi.material && bj.material) {
              cm = this.getContactMaterial(bi.material, bj.material) || this.defaultContactMaterial;
            } else {
              cm = this.defaultContactMaterial;
            }
            var mu = cm.friction;
            if (bi.material && bj.material) {
              if (bi.material.friction >= 0 && bj.material.friction >= 0) {
                mu = bi.material.friction * bj.material.friction;
              }
              if (bi.material.restitution >= 0 && bj.material.restitution >= 0) {
                c.restitution = bi.material.restitution * bj.material.restitution;
              }
            }
            solver.addEquation(c);
            if (bi.allowSleep && bi.type === Body.DYNAMIC && bi.sleepState === Body.SLEEPING && bj.sleepState === Body.AWAKE && bj.type !== Body.STATIC) {
              var speedSquaredB = bj.velocity.norm2() + bj.angularVelocity.norm2();
              var speedLimitSquaredB = Math.pow(bj.sleepSpeedLimit, 2);
              if (speedSquaredB >= speedLimitSquaredB * 2) {
                bi._wakeUpAfterNarrowphase = true;
              }
            }
            if (bj.allowSleep && bj.type === Body.DYNAMIC && bj.sleepState === Body.SLEEPING && bi.sleepState === Body.AWAKE && bi.type !== Body.STATIC) {
              var speedSquaredA = bi.velocity.norm2() + bi.angularVelocity.norm2();
              var speedLimitSquaredA = Math.pow(bi.sleepSpeedLimit, 2);
              if (speedSquaredA >= speedLimitSquaredA * 2) {
                bj._wakeUpAfterNarrowphase = true;
              }
            }
            this.collisionMatrix.set(bi, bj, true);
            if (!this.collisionMatrixPrevious.get(bi, bj)) {
              World_step_collideEvent.body = bj;
              World_step_collideEvent.contact = c;
              bi.dispatchEvent(World_step_collideEvent);
              World_step_collideEvent.body = bi;
              bj.dispatchEvent(World_step_collideEvent);
            }
          }
          if (doProfiling) {
            profile.makeContactConstraints = performance.now() - profilingStart;
            profilingStart = performance.now();
          }
          for (i = 0; i !== N; i++) {
            var bi = bodies[i];
            if (bi._wakeUpAfterNarrowphase) {
              bi.wakeUp();
              bi._wakeUpAfterNarrowphase = false;
            }
          }
          var Nconstraints = constraints.length;
          for (i = 0; i !== Nconstraints; i++) {
            var c = constraints[i];
            c.update();
            for (var j = 0,
                Neq = c.equations.length; j !== Neq; j++) {
              var eq = c.equations[j];
              solver.addEquation(eq);
            }
          }
          solver.solve(dt, this);
          if (doProfiling) {
            profile.solve = performance.now() - profilingStart;
          }
          solver.removeAllEquations();
          var pow = Math.pow;
          for (i = 0; i !== N; i++) {
            var bi = bodies[i];
            if (bi.type & DYNAMIC) {
              var ld = pow(1.0 - bi.linearDamping, dt);
              var v = bi.velocity;
              v.mult(ld, v);
              var av = bi.angularVelocity;
              if (av) {
                var ad = pow(1.0 - bi.angularDamping, dt);
                av.mult(ad, av);
              }
            }
          }
          this.dispatchEvent(World_step_preStepEvent);
          for (i = 0; i !== N; i++) {
            var bi = bodies[i];
            if (bi.preStep) {
              bi.preStep.call(bi);
            }
          }
          if (doProfiling) {
            profilingStart = performance.now();
          }
          var q = World_step_step_q;
          var w = World_step_step_w;
          var wq = World_step_step_wq;
          var stepnumber = this.stepnumber;
          var DYNAMIC_OR_KINEMATIC = Body.DYNAMIC | Body.KINEMATIC;
          var quatNormalize = stepnumber % (this.quatNormalizeSkip + 1) === 0;
          var quatNormalizeFast = this.quatNormalizeFast;
          var half_dt = dt * 0.5;
          var PLANE = Shape.types.PLANE,
              CONVEX = Shape.types.CONVEXPOLYHEDRON;
          for (i = 0; i !== N; i++) {
            var b = bodies[i],
                force = b.force,
                tau = b.torque;
            if ((b.type & DYNAMIC_OR_KINEMATIC) && b.sleepState !== Body.SLEEPING) {
              var velo = b.velocity,
                  angularVelo = b.angularVelocity,
                  pos = b.position,
                  quat = b.quaternion,
                  invMass = b.invMass,
                  invInertia = b.invInertiaWorld;
              velo.x += force.x * invMass * dt;
              velo.y += force.y * invMass * dt;
              velo.z += force.z * invMass * dt;
              if (b.angularVelocity) {
                invInertia.vmult(tau, invI_tau_dt);
                invI_tau_dt.mult(dt, invI_tau_dt);
                invI_tau_dt.vadd(angularVelo, angularVelo);
              }
              pos.x += velo.x * dt;
              pos.y += velo.y * dt;
              pos.z += velo.z * dt;
              if (b.angularVelocity) {
                w.set(angularVelo.x, angularVelo.y, angularVelo.z, 0);
                w.mult(quat, wq);
                quat.x += half_dt * wq.x;
                quat.y += half_dt * wq.y;
                quat.z += half_dt * wq.z;
                quat.w += half_dt * wq.w;
                if (quatNormalize) {
                  if (quatNormalizeFast) {
                    quat.normalizeFast();
                  } else {
                    quat.normalize();
                  }
                }
              }
              if (b.aabb) {
                b.aabbNeedsUpdate = true;
              }
              if (b.updateInertiaWorld) {
                b.updateInertiaWorld();
              }
            }
          }
          this.clearForces();
          this.broadphase.dirty = true;
          if (doProfiling) {
            profile.integrate = performance.now() - profilingStart;
          }
          this.time += dt;
          this.stepnumber += 1;
          this.dispatchEvent(World_step_postStepEvent);
          for (i = 0; i !== N; i++) {
            var bi = bodies[i];
            var postStep = bi.postStep;
            if (postStep) {
              postStep.call(bi);
            }
          }
          if (this.allowSleep) {
            for (i = 0; i !== N; i++) {
              bodies[i].sleepTick(this.time);
            }
          }
        };
        World.prototype.clearForces = function() {
          var bodies = this.bodies;
          var N = bodies.length;
          for (var i = 0; i !== N; i++) {
            var b = bodies[i],
                force = b.force,
                tau = b.torque;
            b.force.set(0, 0, 0);
            b.torque.set(0, 0, 0);
          }
        };
      }, {
        "../collision/AABB": 3,
        "../collision/ArrayCollisionMatrix": 4,
        "../collision/NaiveBroadphase": 7,
        "../collision/Ray": 9,
        "../collision/RaycastResult": 10,
        "../equations/ContactEquation": 19,
        "../equations/FrictionEquation": 21,
        "../material/ContactMaterial": 24,
        "../material/Material": 25,
        "../math/Quaternion": 28,
        "../math/Vec3": 30,
        "../objects/Body": 31,
        "../shapes/Shape": 43,
        "../solver/GSSolver": 46,
        "../utils/EventTarget": 49,
        "../utils/TupleDictionary": 52,
        "../utils/Vec3Pool": 54,
        "./Narrowphase": 55
      }]
    }, {}, [2])(2);
  });
  return module.exports;
});

$__System.registerDynamic("2f", [], false, function($__require, $__exports, $__module) {
  var _retrieveGlobal = $__System.get("@@global-helpers").prepareGlobal($__module.id, null, null);
  (function() {
    THREE.ShaderLib['sky'] = {
      uniforms: {
        luminance: {value: 1},
        turbidity: {value: 2},
        reileigh: {value: 1},
        mieCoefficient: {value: 0.005},
        mieDirectionalG: {value: 0.8},
        sunPosition: {value: new THREE.Vector3()}
      },
      vertexShader: ["varying vec3 vWorldPosition;", "void main() {", "vec4 worldPosition = modelMatrix * vec4( position, 1.0 );", "vWorldPosition = worldPosition.xyz;", "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", "}"].join("\n"),
      fragmentShader: ["uniform sampler2D skySampler;", "uniform vec3 sunPosition;", "varying vec3 vWorldPosition;", "vec3 cameraPos = vec3(0., 0., 0.);", "// uniform sampler2D sDiffuse;", "// const float turbidity = 10.0; //", "// const float reileigh = 2.; //", "// const float luminance = 1.0; //", "// const float mieCoefficient = 0.005;", "// const float mieDirectionalG = 0.8;", "uniform float luminance;", "uniform float turbidity;", "uniform float reileigh;", "uniform float mieCoefficient;", "uniform float mieDirectionalG;", "// constants for atmospheric scattering", "const float e = 2.71828182845904523536028747135266249775724709369995957;", "const float pi = 3.141592653589793238462643383279502884197169;", "const float n = 1.0003; // refractive index of air", "const float N = 2.545E25; // number of molecules per unit volume for air at", "// 288.15K and 1013mb (sea level -45 celsius)", "const float pn = 0.035;	// depolatization factor for standard air", "// wavelength of used primaries, according to preetham", "const vec3 lambda = vec3(680E-9, 550E-9, 450E-9);", "// mie stuff", "// K coefficient for the primaries", "const vec3 K = vec3(0.686, 0.678, 0.666);", "const float v = 4.0;", "// optical length at zenith for molecules", "const float rayleighZenithLength = 8.4E3;", "const float mieZenithLength = 1.25E3;", "const vec3 up = vec3(0.0, 1.0, 0.0);", "const float EE = 1000.0;", "const float sunAngularDiameterCos = 0.999956676946448443553574619906976478926848692873900859324;", "// 66 arc seconds -> degrees, and the cosine of that", "// earth shadow hack", "const float cutoffAngle = pi/1.95;", "const float steepness = 1.5;", "vec3 totalRayleigh(vec3 lambda)", "{", "return (8.0 * pow(pi, 3.0) * pow(pow(n, 2.0) - 1.0, 2.0) * (6.0 + 3.0 * pn)) / (3.0 * N * pow(lambda, vec3(4.0)) * (6.0 - 7.0 * pn));", "}", "// A simplied version of the total Reayleigh scattering to works on browsers that use ANGLE", "vec3 simplifiedRayleigh()", "{", "return 0.0005 / vec3(94, 40, 18);", "}", "float rayleighPhase(float cosTheta)", "{	 ", "return (3.0 / (16.0*pi)) * (1.0 + pow(cosTheta, 2.0));", "//	return (1.0 / (3.0*pi)) * (1.0 + pow(cosTheta, 2.0));", "//	return (3.0 / 4.0) * (1.0 + pow(cosTheta, 2.0));", "}", "vec3 totalMie(vec3 lambda, vec3 K, float T)", "{", "float c = (0.2 * T ) * 10E-18;", "return 0.434 * c * pi * pow((2.0 * pi) / lambda, vec3(v - 2.0)) * K;", "}", "float hgPhase(float cosTheta, float g)", "{", "return (1.0 / (4.0*pi)) * ((1.0 - pow(g, 2.0)) / pow(1.0 - 2.0*g*cosTheta + pow(g, 2.0), 1.5));", "}", "float sunIntensity(float zenithAngleCos)", "{", "return EE * max(0.0, 1.0 - pow(e, -((cutoffAngle - acos(zenithAngleCos))/steepness)));", "}", "// float logLuminance(vec3 c)", "// {", "// 	return log(c.r * 0.2126 + c.g * 0.7152 + c.b * 0.0722);", "// }", "// Filmic ToneMapping http://filmicgames.com/archives/75", "float A = 0.15;", "float B = 0.50;", "float C = 0.10;", "float D = 0.20;", "float E = 0.02;", "float F = 0.30;", "float W = 1000.0;", "vec3 Uncharted2Tonemap(vec3 x)", "{", "return ((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F))-E/F;", "}", "void main() ", "{", "float sunfade = 1.0-clamp(1.0-exp((sunPosition.y/450000.0)),0.0,1.0);", "// luminance =  1.0 ;// vWorldPosition.y / 450000. + 0.5; //sunPosition.y / 450000. * 1. + 0.5;", "// gl_FragColor = vec4(sunfade, sunfade, sunfade, 1.0);", "float reileighCoefficient = reileigh - (1.0* (1.0-sunfade));", "vec3 sunDirection = normalize(sunPosition);", "float sunE = sunIntensity(dot(sunDirection, up));", "// extinction (absorbtion + out scattering) ", "// rayleigh coefficients", "vec3 betaR = simplifiedRayleigh() * reileighCoefficient;", "// mie coefficients", "vec3 betaM = totalMie(lambda, K, turbidity) * mieCoefficient;", "// optical length", "// cutoff angle at 90 to avoid singularity in next formula.", "float zenithAngle = acos(max(0.0, dot(up, normalize(vWorldPosition - cameraPos))));", "float sR = rayleighZenithLength / (cos(zenithAngle) + 0.15 * pow(93.885 - ((zenithAngle * 180.0) / pi), -1.253));", "float sM = mieZenithLength / (cos(zenithAngle) + 0.15 * pow(93.885 - ((zenithAngle * 180.0) / pi), -1.253));", "// combined extinction factor	", "vec3 Fex = exp(-(betaR * sR + betaM * sM));", "// in scattering", "float cosTheta = dot(normalize(vWorldPosition - cameraPos), sunDirection);", "float rPhase = rayleighPhase(cosTheta*0.5+0.5);", "vec3 betaRTheta = betaR * rPhase;", "float mPhase = hgPhase(cosTheta, mieDirectionalG);", "vec3 betaMTheta = betaM * mPhase;", "vec3 Lin = pow(sunE * ((betaRTheta + betaMTheta) / (betaR + betaM)) * (1.0 - Fex),vec3(1.5));", "Lin *= mix(vec3(1.0),pow(sunE * ((betaRTheta + betaMTheta) / (betaR + betaM)) * Fex,vec3(1.0/2.0)),clamp(pow(1.0-dot(up, sunDirection),5.0),0.0,1.0));", "//nightsky", "vec3 direction = normalize(vWorldPosition - cameraPos);", "float theta = acos(direction.y); // elevation --> y-axis, [-pi/2, pi/2]", "float phi = atan(direction.z, direction.x); // azimuth --> x-axis [-pi/2, pi/2]", "vec2 uv = vec2(phi, theta) / vec2(2.0*pi, pi) + vec2(0.5, 0.0);", "// vec3 L0 = texture2D(skySampler, uv).rgb+0.1 * Fex;", "vec3 L0 = vec3(0.1) * Fex;", "// composition + solar disc", "//if (cosTheta > sunAngularDiameterCos)", "float sundisk = smoothstep(sunAngularDiameterCos,sunAngularDiameterCos+0.00002,cosTheta);", "// if (normalize(vWorldPosition - cameraPos).y>0.0)", "L0 += (sunE * 19000.0 * Fex)*sundisk;", "vec3 whiteScale = 1.0/Uncharted2Tonemap(vec3(W));", "vec3 texColor = (Lin+L0);   ", "texColor *= 0.04 ;", "texColor += vec3(0.0,0.001,0.0025)*0.3;", "float g_fMaxLuminance = 1.0;", "float fLumScaled = 0.1 / luminance;     ", "float fLumCompressed = (fLumScaled * (1.0 + (fLumScaled / (g_fMaxLuminance * g_fMaxLuminance)))) / (1.0 + fLumScaled); ", "float ExposureBias = fLumCompressed;", "vec3 curr = Uncharted2Tonemap((log2(2.0/pow(luminance,4.0)))*texColor);", "vec3 color = curr*whiteScale;", "vec3 retColor = pow(color,vec3(1.0/(1.2+(1.2*sunfade))));", "gl_FragColor.rgb = retColor;", "gl_FragColor.a = 1.0;", "}"].join("\n")
    };
    THREE.Sky = function() {
      var skyShader = THREE.ShaderLib["sky"];
      var skyUniforms = THREE.UniformsUtils.clone(skyShader.uniforms);
      var skyMat = new THREE.ShaderMaterial({
        fragmentShader: skyShader.fragmentShader,
        vertexShader: skyShader.vertexShader,
        uniforms: skyUniforms,
        side: THREE.BackSide
      });
      var skyGeo = new THREE.SphereBufferGeometry(450000, 32, 15);
      var skyMesh = new THREE.Mesh(skyGeo, skyMat);
      this.mesh = skyMesh;
      this.uniforms = skyUniforms;
    };
  })();
  return _retrieveGlobal();
});

$__System.registerDynamic("2d", [], false, function($__require, $__exports, $__module) {
  var _retrieveGlobal = $__System.get("@@global-helpers").prepareGlobal($__module.id, null, null);
  (function() {
    THREE.ColladaLoader = function() {
      var COLLADA = null;
      var scene = null;
      var visualScene;
      var kinematicsModel;
      var readyCallbackFunc = null;
      var sources = {};
      var images = {};
      var animations = {};
      var controllers = {};
      var geometries = {};
      var materials = {};
      var effects = {};
      var cameras = {};
      var lights = {};
      var animData;
      var kinematics;
      var visualScenes;
      var kinematicsModels;
      var baseUrl;
      var morphs;
      var skins;
      var flip_uv = true;
      var preferredShading = THREE.SmoothShading;
      var options = {
        centerGeometry: false,
        convertUpAxis: false,
        subdivideFaces: true,
        upAxis: 'Y',
        defaultEnvMap: null
      };
      var colladaUnit = 1.0;
      var colladaUp = 'Y';
      var upConversion = null;
      function load(url, readyCallback, progressCallback, failCallback) {
        var length = 0;
        if (document.implementation && document.implementation.createDocument) {
          var request = new XMLHttpRequest();
          request.onreadystatechange = function() {
            if (request.readyState === 4) {
              if (request.status === 0 || request.status === 200) {
                if (request.response) {
                  readyCallbackFunc = readyCallback;
                  parse(request.response, undefined, url);
                } else {
                  if (failCallback) {
                    failCallback({
                      type: 'error',
                      url: url
                    });
                  } else {
                    console.error("ColladaLoader: Empty or non-existing file (" + url + ")");
                  }
                }
              } else {
                if (failCallback) {
                  failCallback({
                    type: 'error',
                    url: url
                  });
                } else {
                  console.error('ColladaLoader: Couldn\'t load "' + url + '" (' + request.status + ')');
                }
              }
            } else if (request.readyState === 3) {
              if (progressCallback) {
                if (length === 0) {
                  length = request.getResponseHeader("Content-Length");
                }
                progressCallback({
                  total: length,
                  loaded: request.responseText.length
                });
              }
            }
          };
          request.open("GET", url, true);
          request.send(null);
        } else {
          alert("Don't know how to parse XML!");
        }
      }
      function parse(text, callBack, url) {
        COLLADA = new DOMParser().parseFromString(text, 'text/xml');
        callBack = callBack || readyCallbackFunc;
        if (url !== undefined) {
          var parts = url.split('/');
          parts.pop();
          baseUrl = (parts.length < 1 ? '.' : parts.join('/')) + '/';
        }
        parseAsset();
        setUpConversion();
        images = parseLib("library_images image", _Image, "image");
        materials = parseLib("library_materials material", Material, "material");
        effects = parseLib("library_effects effect", Effect, "effect");
        geometries = parseLib("library_geometries geometry", Geometry, "geometry");
        cameras = parseLib("library_cameras camera", Camera, "camera");
        lights = parseLib("library_lights light", Light, "light");
        controllers = parseLib("library_controllers controller", Controller, "controller");
        animations = parseLib("library_animations animation", Animation, "animation");
        visualScenes = parseLib("library_visual_scenes visual_scene", VisualScene, "visual_scene");
        kinematicsModels = parseLib("library_kinematics_models kinematics_model", KinematicsModel, "kinematics_model");
        morphs = [];
        skins = [];
        visualScene = parseScene();
        scene = new THREE.Group();
        for (var i = 0; i < visualScene.nodes.length; i++) {
          scene.add(createSceneGraph(visualScene.nodes[i]));
        }
        scene.scale.multiplyScalar(colladaUnit);
        createAnimations();
        kinematicsModel = parseKinematicsModel();
        createKinematics();
        var result = {
          scene: scene,
          morphs: morphs,
          skins: skins,
          animations: animData,
          kinematics: kinematics,
          dae: {
            images: images,
            materials: materials,
            cameras: cameras,
            lights: lights,
            effects: effects,
            geometries: geometries,
            controllers: controllers,
            animations: animations,
            visualScenes: visualScenes,
            visualScene: visualScene,
            scene: visualScene,
            kinematicsModels: kinematicsModels,
            kinematicsModel: kinematicsModel
          }
        };
        if (callBack) {
          callBack(result);
        }
        return result;
      }
      function setPreferredShading(shading) {
        preferredShading = shading;
      }
      function parseAsset() {
        var elements = COLLADA.querySelectorAll('asset');
        var element = elements[0];
        if (element && element.childNodes) {
          for (var i = 0; i < element.childNodes.length; i++) {
            var child = element.childNodes[i];
            switch (child.nodeName) {
              case 'unit':
                var meter = child.getAttribute('meter');
                if (meter) {
                  colladaUnit = parseFloat(meter);
                }
                break;
              case 'up_axis':
                colladaUp = child.textContent.charAt(0);
                break;
            }
          }
        }
      }
      function parseLib(q, classSpec, prefix) {
        var elements = COLLADA.querySelectorAll(q);
        var lib = {};
        var i = 0;
        var elementsLength = elements.length;
        for (var j = 0; j < elementsLength; j++) {
          var element = elements[j];
          var daeElement = (new classSpec()).parse(element);
          if (!daeElement.id || daeElement.id.length === 0)
            daeElement.id = prefix + (i++);
          lib[daeElement.id] = daeElement;
        }
        return lib;
      }
      function parseScene() {
        var sceneElement = COLLADA.querySelectorAll('scene instance_visual_scene')[0];
        if (sceneElement) {
          var url = sceneElement.getAttribute('url').replace(/^#/, '');
          return visualScenes[url.length > 0 ? url : 'visual_scene0'];
        } else {
          return null;
        }
      }
      function parseKinematicsModel() {
        var kinematicsModelElement = COLLADA.querySelectorAll('instance_kinematics_model')[0];
        if (kinematicsModelElement) {
          var url = kinematicsModelElement.getAttribute('url').replace(/^#/, '');
          return kinematicsModels[url.length > 0 ? url : 'kinematics_model0'];
        } else {
          return null;
        }
      }
      function createAnimations() {
        animData = [];
        recurseHierarchy(scene);
      }
      function recurseHierarchy(node) {
        var n = visualScene.getChildById(node.colladaId, true),
            newData = null;
        if (n && n.keys) {
          newData = {
            fps: 60,
            hierarchy: [{
              node: n,
              keys: n.keys,
              sids: n.sids
            }],
            node: node,
            name: 'animation_' + node.name,
            length: 0
          };
          animData.push(newData);
          for (var i = 0,
              il = n.keys.length; i < il; i++) {
            newData.length = Math.max(newData.length, n.keys[i].time);
          }
        } else {
          newData = {hierarchy: [{
              keys: [],
              sids: []
            }]};
        }
        for (var i = 0,
            il = node.children.length; i < il; i++) {
          var d = recurseHierarchy(node.children[i]);
          for (var j = 0,
              jl = d.hierarchy.length; j < jl; j++) {
            newData.hierarchy.push({
              keys: [],
              sids: []
            });
          }
        }
        return newData;
      }
      function calcAnimationBounds() {
        var start = 1000000;
        var end = -start;
        var frames = 0;
        var ID;
        for (var id in animations) {
          var animation = animations[id];
          ID = ID || animation.id;
          for (var i = 0; i < animation.sampler.length; i++) {
            var sampler = animation.sampler[i];
            sampler.create();
            start = Math.min(start, sampler.startTime);
            end = Math.max(end, sampler.endTime);
            frames = Math.max(frames, sampler.input.length);
          }
        }
        return {
          start: start,
          end: end,
          frames: frames,
          ID: ID
        };
      }
      function createMorph(geometry, ctrl) {
        var morphCtrl = ctrl instanceof InstanceController ? controllers[ctrl.url] : ctrl;
        if (!morphCtrl || !morphCtrl.morph) {
          console.log("could not find morph controller!");
          return;
        }
        var morph = morphCtrl.morph;
        for (var i = 0; i < morph.targets.length; i++) {
          var target_id = morph.targets[i];
          var daeGeometry = geometries[target_id];
          if (!daeGeometry.mesh || !daeGeometry.mesh.primitives || !daeGeometry.mesh.primitives.length) {
            continue;
          }
          var target = daeGeometry.mesh.primitives[0].geometry;
          if (target.vertices.length === geometry.vertices.length) {
            geometry.morphTargets.push({
              name: "target_1",
              vertices: target.vertices
            });
          }
        }
        geometry.morphTargets.push({
          name: "target_Z",
          vertices: geometry.vertices
        });
      }
      function createSkin(geometry, ctrl, applyBindShape) {
        var skinCtrl = controllers[ctrl.url];
        if (!skinCtrl || !skinCtrl.skin) {
          console.log("could not find skin controller!");
          return;
        }
        if (!ctrl.skeleton || !ctrl.skeleton.length) {
          console.log("could not find the skeleton for the skin!");
          return;
        }
        var skin = skinCtrl.skin;
        var skeleton = visualScene.getChildById(ctrl.skeleton[0]);
        var hierarchy = [];
        applyBindShape = applyBindShape !== undefined ? applyBindShape : true;
        var bones = [];
        geometry.skinWeights = [];
        geometry.skinIndices = [];
        if (applyBindShape) {
          for (var i = 0; i < geometry.vertices.length; i++) {
            geometry.vertices[i].applyMatrix4(skin.bindShapeMatrix);
          }
        }
      }
      function setupSkeleton(node, bones, frame, parent) {
        node.world = node.world || new THREE.Matrix4();
        node.localworld = node.localworld || new THREE.Matrix4();
        node.world.copy(node.matrix);
        node.localworld.copy(node.matrix);
        if (node.channels && node.channels.length) {
          var channel = node.channels[0];
          var m = channel.sampler.output[frame];
          if (m instanceof THREE.Matrix4) {
            node.world.copy(m);
            node.localworld.copy(m);
            if (frame === 0)
              node.matrix.copy(m);
          }
        }
        if (parent) {
          node.world.multiplyMatrices(parent, node.world);
        }
        bones.push(node);
        for (var i = 0; i < node.nodes.length; i++) {
          setupSkeleton(node.nodes[i], bones, frame, node.world);
        }
      }
      function setupSkinningMatrices(bones, skin) {
        for (var i = 0; i < bones.length; i++) {
          var bone = bones[i];
          var found = -1;
          if (bone.type != 'JOINT')
            continue;
          for (var j = 0; j < skin.joints.length; j++) {
            if (bone.sid === skin.joints[j]) {
              found = j;
              break;
            }
          }
          if (found >= 0) {
            var inv = skin.invBindMatrices[found];
            bone.invBindMatrix = inv;
            bone.skinningMatrix = new THREE.Matrix4();
            bone.skinningMatrix.multiplyMatrices(bone.world, inv);
            bone.animatrix = new THREE.Matrix4();
            bone.animatrix.copy(bone.localworld);
            bone.weights = [];
            for (var j = 0; j < skin.weights.length; j++) {
              for (var k = 0; k < skin.weights[j].length; k++) {
                var w = skin.weights[j][k];
                if (w.joint === found) {
                  bone.weights.push(w);
                }
              }
            }
          } else {
            console.warn("ColladaLoader: Could not find joint '" + bone.sid + "'.");
            bone.skinningMatrix = new THREE.Matrix4();
            bone.weights = [];
          }
        }
      }
      function flattenSkeleton(skeleton) {
        var list = [];
        var walk = function(parentid, node, list) {
          var bone = {};
          bone.name = node.sid;
          bone.parent = parentid;
          bone.matrix = node.matrix;
          var data = [new THREE.Vector3(), new THREE.Quaternion(), new THREE.Vector3()];
          bone.matrix.decompose(data[0], data[1], data[2]);
          bone.pos = [data[0].x, data[0].y, data[0].z];
          bone.scl = [data[2].x, data[2].y, data[2].z];
          bone.rotq = [data[1].x, data[1].y, data[1].z, data[1].w];
          list.push(bone);
          for (var i in node.nodes) {
            walk(node.sid, node.nodes[i], list);
          }
        };
        walk(-1, skeleton, list);
        return list;
      }
      function skinToBindPose(geometry, skeleton, skinController) {
        var bones = [];
        setupSkeleton(skeleton, bones, -1);
        setupSkinningMatrices(bones, skinController.skin);
        var v = new THREE.Vector3();
        var skinned = [];
        for (var i = 0; i < geometry.vertices.length; i++) {
          skinned.push(new THREE.Vector3());
        }
        for (i = 0; i < bones.length; i++) {
          if (bones[i].type != 'JOINT')
            continue;
          for (var j = 0; j < bones[i].weights.length; j++) {
            var w = bones[i].weights[j];
            var vidx = w.index;
            var weight = w.weight;
            var o = geometry.vertices[vidx];
            var s = skinned[vidx];
            v.x = o.x;
            v.y = o.y;
            v.z = o.z;
            v.applyMatrix4(bones[i].skinningMatrix);
            s.x += (v.x * weight);
            s.y += (v.y * weight);
            s.z += (v.z * weight);
          }
        }
        for (var i = 0; i < geometry.vertices.length; i++) {
          geometry.vertices[i] = skinned[i];
        }
      }
      function applySkin(geometry, instanceCtrl, frame) {
        var skinController = controllers[instanceCtrl.url];
        frame = frame !== undefined ? frame : 40;
        if (!skinController || !skinController.skin) {
          console.log('ColladaLoader: Could not find skin controller.');
          return;
        }
        if (!instanceCtrl.skeleton || !instanceCtrl.skeleton.length) {
          console.log('ColladaLoader: Could not find the skeleton for the skin. ');
          return;
        }
        var animationBounds = calcAnimationBounds();
        var skeleton = visualScene.getChildById(instanceCtrl.skeleton[0], true) || visualScene.getChildBySid(instanceCtrl.skeleton[0], true);
        var bonelist = flattenSkeleton(skeleton);
        var joints = skinController.skin.joints;
        var sortedbones = [];
        for (var i = 0; i < joints.length; i++) {
          for (var j = 0; j < bonelist.length; j++) {
            if (bonelist[j].name === joints[i]) {
              sortedbones[i] = bonelist[j];
            }
          }
        }
        for (var i = 0; i < sortedbones.length; i++) {
          for (var j = 0; j < sortedbones.length; j++) {
            if (sortedbones[i].parent === sortedbones[j].name) {
              sortedbones[i].parent = j;
            }
          }
        }
        var i,
            j,
            w,
            vidx,
            weight;
        var v = new THREE.Vector3(),
            o,
            s;
        for (i = 0; i < geometry.vertices.length; i++) {
          geometry.vertices[i].applyMatrix4(skinController.skin.bindShapeMatrix);
        }
        var skinIndices = [];
        var skinWeights = [];
        var weights = skinController.skin.weights;
        for (var i = 0; i < weights.length; i++) {
          var indicies = new THREE.Vector4(weights[i][0] ? weights[i][0].joint : 0, weights[i][1] ? weights[i][1].joint : 0, weights[i][2] ? weights[i][2].joint : 0, weights[i][3] ? weights[i][3].joint : 0);
          var weight = new THREE.Vector4(weights[i][0] ? weights[i][0].weight : 0, weights[i][1] ? weights[i][1].weight : 0, weights[i][2] ? weights[i][2].weight : 0, weights[i][3] ? weights[i][3].weight : 0);
          skinIndices.push(indicies);
          skinWeights.push(weight);
        }
        geometry.skinIndices = skinIndices;
        geometry.skinWeights = skinWeights;
        geometry.bones = sortedbones;
        var animationdata = {
          "name": animationBounds.ID,
          "fps": 30,
          "length": animationBounds.frames / 30,
          "hierarchy": []
        };
        for (var j = 0; j < sortedbones.length; j++) {
          animationdata.hierarchy.push({
            parent: sortedbones[j].parent,
            name: sortedbones[j].name,
            keys: []
          });
        }
        console.log('ColladaLoader:', animationBounds.ID + ' has ' + sortedbones.length + ' bones.');
        skinToBindPose(geometry, skeleton, skinController);
        for (frame = 0; frame < animationBounds.frames; frame++) {
          var bones = [];
          var skinned = [];
          setupSkeleton(skeleton, bones, frame);
          setupSkinningMatrices(bones, skinController.skin);
          for (var i = 0; i < bones.length; i++) {
            for (var j = 0; j < animationdata.hierarchy.length; j++) {
              if (animationdata.hierarchy[j].name === bones[i].sid) {
                var key = {};
                key.time = (frame / 30);
                key.matrix = bones[i].animatrix;
                if (frame === 0)
                  bones[i].matrix = key.matrix;
                var data = [new THREE.Vector3(), new THREE.Quaternion(), new THREE.Vector3()];
                key.matrix.decompose(data[0], data[1], data[2]);
                key.pos = [data[0].x, data[0].y, data[0].z];
                key.scl = [data[2].x, data[2].y, data[2].z];
                key.rot = data[1];
                animationdata.hierarchy[j].keys.push(key);
              }
            }
          }
          geometry.animation = animationdata;
        }
      }
      function createKinematics() {
        if (kinematicsModel && kinematicsModel.joints.length === 0) {
          kinematics = undefined;
          return;
        }
        var jointMap = {};
        var _addToMap = function(jointIndex, parentVisualElement) {
          var parentVisualElementId = parentVisualElement.getAttribute('id');
          var colladaNode = visualScene.getChildById(parentVisualElementId, true);
          var joint = kinematicsModel.joints[jointIndex];
          scene.traverse(function(node) {
            if (node.colladaId == parentVisualElementId) {
              jointMap[jointIndex] = {
                node: node,
                transforms: colladaNode.transforms,
                joint: joint,
                position: joint.zeroPosition
              };
            }
          });
        };
        kinematics = {
          joints: kinematicsModel && kinematicsModel.joints,
          getJointValue: function(jointIndex) {
            var jointData = jointMap[jointIndex];
            if (jointData) {
              return jointData.position;
            } else {
              console.log('getJointValue: joint ' + jointIndex + ' doesn\'t exist');
            }
          },
          setJointValue: function(jointIndex, value) {
            var jointData = jointMap[jointIndex];
            if (jointData) {
              var joint = jointData.joint;
              if (value > joint.limits.max || value < joint.limits.min) {
                console.log('setJointValue: joint ' + jointIndex + ' value ' + value + ' outside of limits (min: ' + joint.limits.min + ', max: ' + joint.limits.max + ')');
              } else if (joint.static) {
                console.log('setJointValue: joint ' + jointIndex + ' is static');
              } else {
                var threejsNode = jointData.node;
                var axis = joint.axis;
                var transforms = jointData.transforms;
                var matrix = new THREE.Matrix4();
                for (i = 0; i < transforms.length; i++) {
                  var transform = transforms[i];
                  if (transform.sid && transform.sid.indexOf('joint' + jointIndex) !== -1) {
                    switch (joint.type) {
                      case 'revolute':
                        matrix.multiply(m1.makeRotationAxis(axis, THREE.Math.degToRad(value)));
                        break;
                      case 'prismatic':
                        matrix.multiply(m1.makeTranslation(axis.x * value, axis.y * value, axis.z * value));
                        break;
                      default:
                        console.warn('setJointValue: unknown joint type: ' + joint.type);
                        break;
                    }
                  } else {
                    var m1 = new THREE.Matrix4();
                    switch (transform.type) {
                      case 'matrix':
                        matrix.multiply(transform.obj);
                        break;
                      case 'translate':
                        matrix.multiply(m1.makeTranslation(transform.obj.x, transform.obj.y, transform.obj.z));
                        break;
                      case 'rotate':
                        matrix.multiply(m1.makeRotationAxis(transform.obj, transform.angle));
                        break;
                    }
                  }
                }
                var elementsFloat32Arr = matrix.elements;
                var elements = Array.prototype.slice.call(elementsFloat32Arr);
                var elementsRowMajor = [elements[0], elements[4], elements[8], elements[12], elements[1], elements[5], elements[9], elements[13], elements[2], elements[6], elements[10], elements[14], elements[3], elements[7], elements[11], elements[15]];
                threejsNode.matrix.set.apply(threejsNode.matrix, elementsRowMajor);
                threejsNode.matrix.decompose(threejsNode.position, threejsNode.quaternion, threejsNode.scale);
              }
            } else {
              console.log('setJointValue: joint ' + jointIndex + ' doesn\'t exist');
            }
          }
        };
        var element = COLLADA.querySelector('scene instance_kinematics_scene');
        if (element) {
          for (var i = 0; i < element.childNodes.length; i++) {
            var child = element.childNodes[i];
            if (child.nodeType != 1)
              continue;
            switch (child.nodeName) {
              case 'bind_joint_axis':
                var visualTarget = child.getAttribute('target').split('/').pop();
                var axis = child.querySelector('axis param').textContent;
                var jointIndex = parseInt(axis.split('joint').pop().split('.')[0]);
                var visualTargetElement = COLLADA.querySelector('[sid="' + visualTarget + '"]');
                if (visualTargetElement) {
                  var parentVisualElement = visualTargetElement.parentElement;
                  _addToMap(jointIndex, parentVisualElement);
                }
                break;
              default:
                break;
            }
          }
        }
      }
      function createSceneGraph(node, parent) {
        var obj = new THREE.Object3D();
        var skinned = false;
        var skinController;
        var morphController;
        var i,
            j;
        for (i = 0; i < node.controllers.length; i++) {
          var controller = controllers[node.controllers[i].url];
          switch (controller.type) {
            case 'skin':
              if (geometries[controller.skin.source]) {
                var inst_geom = new InstanceGeometry();
                inst_geom.url = controller.skin.source;
                inst_geom.instance_material = node.controllers[i].instance_material;
                node.geometries.push(inst_geom);
                skinned = true;
                skinController = node.controllers[i];
              } else if (controllers[controller.skin.source]) {
                var second = controllers[controller.skin.source];
                morphController = second;
                if (second.morph && geometries[second.morph.source]) {
                  var inst_geom = new InstanceGeometry();
                  inst_geom.url = second.morph.source;
                  inst_geom.instance_material = node.controllers[i].instance_material;
                  node.geometries.push(inst_geom);
                }
              }
              break;
            case 'morph':
              if (geometries[controller.morph.source]) {
                var inst_geom = new InstanceGeometry();
                inst_geom.url = controller.morph.source;
                inst_geom.instance_material = node.controllers[i].instance_material;
                node.geometries.push(inst_geom);
                morphController = node.controllers[i];
              }
              console.log('ColladaLoader: Morph-controller partially supported.');
            default:
              break;
          }
        }
        var double_sided_materials = {};
        for (i = 0; i < node.geometries.length; i++) {
          var instance_geometry = node.geometries[i];
          var instance_materials = instance_geometry.instance_material;
          var geometry = geometries[instance_geometry.url];
          var used_materials = {};
          var used_materials_array = [];
          var num_materials = 0;
          var first_material;
          if (geometry) {
            if (!geometry.mesh || !geometry.mesh.primitives)
              continue;
            if (obj.name.length === 0) {
              obj.name = geometry.id;
            }
            if (instance_materials) {
              for (j = 0; j < instance_materials.length; j++) {
                var instance_material = instance_materials[j];
                var mat = materials[instance_material.target];
                var effect_id = mat.instance_effect.url;
                var shader = effects[effect_id].shader;
                var material3js = shader.material;
                if (geometry.doubleSided) {
                  if (!(instance_material.symbol in double_sided_materials)) {
                    var _copied_material = material3js.clone();
                    _copied_material.side = THREE.DoubleSide;
                    double_sided_materials[instance_material.symbol] = _copied_material;
                  }
                  material3js = double_sided_materials[instance_material.symbol];
                }
                material3js.opacity = !material3js.opacity ? 1 : material3js.opacity;
                used_materials[instance_material.symbol] = num_materials;
                used_materials_array.push(material3js);
                first_material = material3js;
                first_material.name = mat.name === null || mat.name === '' ? mat.id : mat.name;
                num_materials++;
              }
            }
            var mesh;
            var material = first_material || new THREE.MeshLambertMaterial({
              color: 0xdddddd,
              side: geometry.doubleSided ? THREE.DoubleSide : THREE.FrontSide
            });
            var geom = geometry.mesh.geometry3js;
            if (num_materials > 1) {
              material = new THREE.MultiMaterial(used_materials_array);
              for (j = 0; j < geom.faces.length; j++) {
                var face = geom.faces[j];
                face.materialIndex = used_materials[face.daeMaterial];
              }
            }
            if (skinController !== undefined) {
              applySkin(geom, skinController);
              if (geom.morphTargets.length > 0) {
                material.morphTargets = true;
                material.skinning = false;
              } else {
                material.morphTargets = false;
                material.skinning = true;
              }
              mesh = new THREE.SkinnedMesh(geom, material, false);
              mesh.name = 'skin_' + skins.length;
              skins.push(mesh);
            } else if (morphController !== undefined) {
              createMorph(geom, morphController);
              material.morphTargets = true;
              mesh = new THREE.Mesh(geom, material);
              mesh.name = 'morph_' + morphs.length;
              morphs.push(mesh);
            } else {
              if (geom.isLineStrip === true) {
                mesh = new THREE.Line(geom);
              } else {
                mesh = new THREE.Mesh(geom, material);
              }
            }
            obj.add(mesh);
          }
        }
        for (i = 0; i < node.cameras.length; i++) {
          var instance_camera = node.cameras[i];
          var cparams = cameras[instance_camera.url];
          var cam = new THREE.PerspectiveCamera(cparams.yfov, parseFloat(cparams.aspect_ratio), parseFloat(cparams.znear), parseFloat(cparams.zfar));
          obj.add(cam);
        }
        for (i = 0; i < node.lights.length; i++) {
          var light = null;
          var instance_light = node.lights[i];
          var lparams = lights[instance_light.url];
          if (lparams && lparams.technique) {
            var color = lparams.color.getHex();
            var intensity = lparams.intensity;
            var distance = lparams.distance;
            var angle = lparams.falloff_angle;
            switch (lparams.technique) {
              case 'directional':
                light = new THREE.DirectionalLight(color, intensity, distance);
                light.position.set(0, 0, 1);
                break;
              case 'point':
                light = new THREE.PointLight(color, intensity, distance);
                break;
              case 'spot':
                light = new THREE.SpotLight(color, intensity, distance, angle);
                light.position.set(0, 0, 1);
                break;
              case 'ambient':
                light = new THREE.AmbientLight(color);
                break;
            }
          }
          if (light) {
            obj.add(light);
          }
        }
        obj.name = node.name || node.id || "";
        obj.colladaId = node.id || "";
        obj.layer = node.layer || "";
        obj.matrix = node.matrix;
        obj.matrix.decompose(obj.position, obj.quaternion, obj.scale);
        if (options.centerGeometry && obj.geometry) {
          var delta = obj.geometry.center();
          delta.multiply(obj.scale);
          delta.applyQuaternion(obj.quaternion);
          obj.position.sub(delta);
        }
        for (i = 0; i < node.nodes.length; i++) {
          obj.add(createSceneGraph(node.nodes[i], node));
        }
        return obj;
      }
      function getJointId(skin, id) {
        for (var i = 0; i < skin.joints.length; i++) {
          if (skin.joints[i] === id) {
            return i;
          }
        }
      }
      function getLibraryNode(id) {
        var nodes = COLLADA.querySelectorAll('library_nodes node');
        for (var i = 0; i < nodes.length; i++) {
          var attObj = nodes[i].attributes.getNamedItem('id');
          if (attObj && attObj.value === id) {
            return nodes[i];
          }
        }
        return undefined;
      }
      function getChannelsForNode(node) {
        var channels = [];
        var startTime = 1000000;
        var endTime = -1000000;
        for (var id in animations) {
          var animation = animations[id];
          for (var i = 0; i < animation.channel.length; i++) {
            var channel = animation.channel[i];
            var sampler = animation.sampler[i];
            var id = channel.target.split('/')[0];
            if (id == node.id) {
              sampler.create();
              channel.sampler = sampler;
              startTime = Math.min(startTime, sampler.startTime);
              endTime = Math.max(endTime, sampler.endTime);
              channels.push(channel);
            }
          }
        }
        if (channels.length) {
          node.startTime = startTime;
          node.endTime = endTime;
        }
        return channels;
      }
      function calcFrameDuration(node) {
        var minT = 10000000;
        for (var i = 0; i < node.channels.length; i++) {
          var sampler = node.channels[i].sampler;
          for (var j = 0; j < sampler.input.length - 1; j++) {
            var t0 = sampler.input[j];
            var t1 = sampler.input[j + 1];
            minT = Math.min(minT, t1 - t0);
          }
        }
        return minT;
      }
      function calcMatrixAt(node, t) {
        var animated = {};
        var i,
            j;
        for (i = 0; i < node.channels.length; i++) {
          var channel = node.channels[i];
          animated[channel.sid] = channel;
        }
        var matrix = new THREE.Matrix4();
        for (i = 0; i < node.transforms.length; i++) {
          var transform = node.transforms[i];
          var channel = animated[transform.sid];
          if (channel !== undefined) {
            var sampler = channel.sampler;
            var value;
            for (j = 0; j < sampler.input.length - 1; j++) {
              if (sampler.input[j + 1] > t) {
                value = sampler.output[j];
                break;
              }
            }
            if (value !== undefined) {
              if (value instanceof THREE.Matrix4) {
                matrix.multiplyMatrices(matrix, value);
              } else {
                matrix.multiplyMatrices(matrix, transform.matrix);
              }
            } else {
              matrix.multiplyMatrices(matrix, transform.matrix);
            }
          } else {
            matrix.multiplyMatrices(matrix, transform.matrix);
          }
        }
        return matrix;
      }
      function bakeAnimations(node) {
        if (node.channels && node.channels.length) {
          var keys = [],
              sids = [];
          for (var i = 0,
              il = node.channels.length; i < il; i++) {
            var channel = node.channels[i],
                fullSid = channel.fullSid,
                sampler = channel.sampler,
                input = sampler.input,
                transform = node.getTransformBySid(channel.sid),
                member;
            if (channel.arrIndices) {
              member = [];
              for (var j = 0,
                  jl = channel.arrIndices.length; j < jl; j++) {
                member[j] = getConvertedIndex(channel.arrIndices[j]);
              }
            } else {
              member = getConvertedMember(channel.member);
            }
            if (transform) {
              if (sids.indexOf(fullSid) === -1) {
                sids.push(fullSid);
              }
              for (var j = 0,
                  jl = input.length; j < jl; j++) {
                var time = input[j],
                    data = sampler.getData(transform.type, j, member),
                    key = findKey(keys, time);
                if (!key) {
                  key = new Key(time);
                  var timeNdx = findTimeNdx(keys, time);
                  keys.splice(timeNdx === -1 ? keys.length : timeNdx, 0, key);
                }
                key.addTarget(fullSid, transform, member, data);
              }
            } else {
              console.log('Could not find transform "' + channel.sid + '" in node ' + node.id);
            }
          }
          for (var i = 0; i < sids.length; i++) {
            var sid = sids[i];
            for (var j = 0; j < keys.length; j++) {
              var key = keys[j];
              if (!key.hasTarget(sid)) {
                interpolateKeys(keys, key, j, sid);
              }
            }
          }
          node.keys = keys;
          node.sids = sids;
        }
      }
      function findKey(keys, time) {
        var retVal = null;
        for (var i = 0,
            il = keys.length; i < il && retVal === null; i++) {
          var key = keys[i];
          if (key.time === time) {
            retVal = key;
          } else if (key.time > time) {
            break;
          }
        }
        return retVal;
      }
      function findTimeNdx(keys, time) {
        var ndx = -1;
        for (var i = 0,
            il = keys.length; i < il && ndx === -1; i++) {
          var key = keys[i];
          if (key.time >= time) {
            ndx = i;
          }
        }
        return ndx;
      }
      function interpolateKeys(keys, key, ndx, fullSid) {
        var prevKey = getPrevKeyWith(keys, fullSid, ndx ? ndx - 1 : 0),
            nextKey = getNextKeyWith(keys, fullSid, ndx + 1);
        if (prevKey && nextKey) {
          var scale = (key.time - prevKey.time) / (nextKey.time - prevKey.time),
              prevTarget = prevKey.getTarget(fullSid),
              nextData = nextKey.getTarget(fullSid).data,
              prevData = prevTarget.data,
              data;
          if (prevTarget.type === 'matrix') {
            data = prevData;
          } else if (prevData.length) {
            data = [];
            for (var i = 0; i < prevData.length; ++i) {
              data[i] = prevData[i] + (nextData[i] - prevData[i]) * scale;
            }
          } else {
            data = prevData + (nextData - prevData) * scale;
          }
          key.addTarget(fullSid, prevTarget.transform, prevTarget.member, data);
        }
      }
      function getNextKeyWith(keys, fullSid, ndx) {
        for (; ndx < keys.length; ndx++) {
          var key = keys[ndx];
          if (key.hasTarget(fullSid)) {
            return key;
          }
        }
        return null;
      }
      function getPrevKeyWith(keys, fullSid, ndx) {
        ndx = ndx >= 0 ? ndx : ndx + keys.length;
        for (; ndx >= 0; ndx--) {
          var key = keys[ndx];
          if (key.hasTarget(fullSid)) {
            return key;
          }
        }
        return null;
      }
      function _Image() {
        this.id = "";
        this.init_from = "";
      }
      _Image.prototype.parse = function(element) {
        this.id = element.getAttribute('id');
        for (var i = 0; i < element.childNodes.length; i++) {
          var child = element.childNodes[i];
          if (child.nodeName === 'init_from') {
            this.init_from = child.textContent;
          }
        }
        return this;
      };
      function Controller() {
        this.id = "";
        this.name = "";
        this.type = "";
        this.skin = null;
        this.morph = null;
      }
      Controller.prototype.parse = function(element) {
        this.id = element.getAttribute('id');
        this.name = element.getAttribute('name');
        this.type = "none";
        for (var i = 0; i < element.childNodes.length; i++) {
          var child = element.childNodes[i];
          switch (child.nodeName) {
            case 'skin':
              this.skin = (new Skin()).parse(child);
              this.type = child.nodeName;
              break;
            case 'morph':
              this.morph = (new Morph()).parse(child);
              this.type = child.nodeName;
              break;
            default:
              break;
          }
        }
        return this;
      };
      function Morph() {
        this.method = null;
        this.source = null;
        this.targets = null;
        this.weights = null;
      }
      Morph.prototype.parse = function(element) {
        var sources = {};
        var inputs = [];
        var i;
        this.method = element.getAttribute('method');
        this.source = element.getAttribute('source').replace(/^#/, '');
        for (i = 0; i < element.childNodes.length; i++) {
          var child = element.childNodes[i];
          if (child.nodeType != 1)
            continue;
          switch (child.nodeName) {
            case 'source':
              var source = (new Source()).parse(child);
              sources[source.id] = source;
              break;
            case 'targets':
              inputs = this.parseInputs(child);
              break;
            default:
              console.log(child.nodeName);
              break;
          }
        }
        for (i = 0; i < inputs.length; i++) {
          var input = inputs[i];
          var source = sources[input.source];
          switch (input.semantic) {
            case 'MORPH_TARGET':
              this.targets = source.read();
              break;
            case 'MORPH_WEIGHT':
              this.weights = source.read();
              break;
            default:
              break;
          }
        }
        return this;
      };
      Morph.prototype.parseInputs = function(element) {
        var inputs = [];
        for (var i = 0; i < element.childNodes.length; i++) {
          var child = element.childNodes[i];
          if (child.nodeType != 1)
            continue;
          switch (child.nodeName) {
            case 'input':
              inputs.push((new Input()).parse(child));
              break;
            default:
              break;
          }
        }
        return inputs;
      };
      function Skin() {
        this.source = "";
        this.bindShapeMatrix = null;
        this.invBindMatrices = [];
        this.joints = [];
        this.weights = [];
      }
      Skin.prototype.parse = function(element) {
        var sources = {};
        var joints,
            weights;
        this.source = element.getAttribute('source').replace(/^#/, '');
        this.invBindMatrices = [];
        this.joints = [];
        this.weights = [];
        for (var i = 0; i < element.childNodes.length; i++) {
          var child = element.childNodes[i];
          if (child.nodeType != 1)
            continue;
          switch (child.nodeName) {
            case 'bind_shape_matrix':
              var f = _floats(child.textContent);
              this.bindShapeMatrix = getConvertedMat4(f);
              break;
            case 'source':
              var src = new Source().parse(child);
              sources[src.id] = src;
              break;
            case 'joints':
              joints = child;
              break;
            case 'vertex_weights':
              weights = child;
              break;
            default:
              console.log(child.nodeName);
              break;
          }
        }
        this.parseJoints(joints, sources);
        this.parseWeights(weights, sources);
        return this;
      };
      Skin.prototype.parseJoints = function(element, sources) {
        for (var i = 0; i < element.childNodes.length; i++) {
          var child = element.childNodes[i];
          if (child.nodeType != 1)
            continue;
          switch (child.nodeName) {
            case 'input':
              var input = (new Input()).parse(child);
              var source = sources[input.source];
              if (input.semantic === 'JOINT') {
                this.joints = source.read();
              } else if (input.semantic === 'INV_BIND_MATRIX') {
                this.invBindMatrices = source.read();
              }
              break;
            default:
              break;
          }
        }
      };
      Skin.prototype.parseWeights = function(element, sources) {
        var v,
            vcount,
            inputs = [];
        for (var i = 0; i < element.childNodes.length; i++) {
          var child = element.childNodes[i];
          if (child.nodeType != 1)
            continue;
          switch (child.nodeName) {
            case 'input':
              inputs.push((new Input()).parse(child));
              break;
            case 'v':
              v = _ints(child.textContent);
              break;
            case 'vcount':
              vcount = _ints(child.textContent);
              break;
            default:
              break;
          }
        }
        var index = 0;
        for (var i = 0; i < vcount.length; i++) {
          var numBones = vcount[i];
          var vertex_weights = [];
          for (var j = 0; j < numBones; j++) {
            var influence = {};
            for (var k = 0; k < inputs.length; k++) {
              var input = inputs[k];
              var value = v[index + input.offset];
              switch (input.semantic) {
                case 'JOINT':
                  influence.joint = value;
                  break;
                case 'WEIGHT':
                  influence.weight = sources[input.source].data[value];
                  break;
                default:
                  break;
              }
            }
            vertex_weights.push(influence);
            index += inputs.length;
          }
          for (var j = 0; j < vertex_weights.length; j++) {
            vertex_weights[j].index = i;
          }
          this.weights.push(vertex_weights);
        }
      };
      function VisualScene() {
        this.id = "";
        this.name = "";
        this.nodes = [];
        this.scene = new THREE.Group();
      }
      VisualScene.prototype.getChildById = function(id, recursive) {
        for (var i = 0; i < this.nodes.length; i++) {
          var node = this.nodes[i].getChildById(id, recursive);
          if (node) {
            return node;
          }
        }
        return null;
      };
      VisualScene.prototype.getChildBySid = function(sid, recursive) {
        for (var i = 0; i < this.nodes.length; i++) {
          var node = this.nodes[i].getChildBySid(sid, recursive);
          if (node) {
            return node;
          }
        }
        return null;
      };
      VisualScene.prototype.parse = function(element) {
        this.id = element.getAttribute('id');
        this.name = element.getAttribute('name');
        this.nodes = [];
        for (var i = 0; i < element.childNodes.length; i++) {
          var child = element.childNodes[i];
          if (child.nodeType != 1)
            continue;
          switch (child.nodeName) {
            case 'node':
              this.nodes.push((new Node()).parse(child));
              break;
            default:
              break;
          }
        }
        return this;
      };
      function Node() {
        this.id = "";
        this.name = "";
        this.sid = "";
        this.nodes = [];
        this.controllers = [];
        this.transforms = [];
        this.geometries = [];
        this.channels = [];
        this.matrix = new THREE.Matrix4();
      }
      Node.prototype.getChannelForTransform = function(transformSid) {
        for (var i = 0; i < this.channels.length; i++) {
          var channel = this.channels[i];
          var parts = channel.target.split('/');
          var id = parts.shift();
          var sid = parts.shift();
          var dotSyntax = (sid.indexOf(".") >= 0);
          var arrSyntax = (sid.indexOf("(") >= 0);
          var arrIndices;
          var member;
          if (dotSyntax) {
            parts = sid.split(".");
            sid = parts.shift();
            member = parts.shift();
          } else if (arrSyntax) {
            arrIndices = sid.split("(");
            sid = arrIndices.shift();
            for (var j = 0; j < arrIndices.length; j++) {
              arrIndices[j] = parseInt(arrIndices[j].replace(/\)/, ''));
            }
          }
          if (sid === transformSid) {
            channel.info = {
              sid: sid,
              dotSyntax: dotSyntax,
              arrSyntax: arrSyntax,
              arrIndices: arrIndices
            };
            return channel;
          }
        }
        return null;
      };
      Node.prototype.getChildById = function(id, recursive) {
        if (this.id === id) {
          return this;
        }
        if (recursive) {
          for (var i = 0; i < this.nodes.length; i++) {
            var n = this.nodes[i].getChildById(id, recursive);
            if (n) {
              return n;
            }
          }
        }
        return null;
      };
      Node.prototype.getChildBySid = function(sid, recursive) {
        if (this.sid === sid) {
          return this;
        }
        if (recursive) {
          for (var i = 0; i < this.nodes.length; i++) {
            var n = this.nodes[i].getChildBySid(sid, recursive);
            if (n) {
              return n;
            }
          }
        }
        return null;
      };
      Node.prototype.getTransformBySid = function(sid) {
        for (var i = 0; i < this.transforms.length; i++) {
          if (this.transforms[i].sid === sid)
            return this.transforms[i];
        }
        return null;
      };
      Node.prototype.parse = function(element) {
        var url;
        this.id = element.getAttribute('id');
        this.sid = element.getAttribute('sid');
        this.name = element.getAttribute('name');
        this.type = element.getAttribute('type');
        this.layer = element.getAttribute('layer');
        this.type = this.type === 'JOINT' ? this.type : 'NODE';
        this.nodes = [];
        this.transforms = [];
        this.geometries = [];
        this.cameras = [];
        this.lights = [];
        this.controllers = [];
        this.matrix = new THREE.Matrix4();
        for (var i = 0; i < element.childNodes.length; i++) {
          var child = element.childNodes[i];
          if (child.nodeType != 1)
            continue;
          switch (child.nodeName) {
            case 'node':
              this.nodes.push((new Node()).parse(child));
              break;
            case 'instance_camera':
              this.cameras.push((new InstanceCamera()).parse(child));
              break;
            case 'instance_controller':
              this.controllers.push((new InstanceController()).parse(child));
              break;
            case 'instance_geometry':
              this.geometries.push((new InstanceGeometry()).parse(child));
              break;
            case 'instance_light':
              this.lights.push((new InstanceLight()).parse(child));
              break;
            case 'instance_node':
              url = child.getAttribute('url').replace(/^#/, '');
              var iNode = getLibraryNode(url);
              if (iNode) {
                this.nodes.push((new Node()).parse(iNode));
              }
              break;
            case 'rotate':
            case 'translate':
            case 'scale':
            case 'matrix':
            case 'lookat':
            case 'skew':
              this.transforms.push((new Transform()).parse(child));
              break;
            case 'extra':
              break;
            default:
              console.log(child.nodeName);
              break;
          }
        }
        this.channels = getChannelsForNode(this);
        bakeAnimations(this);
        this.updateMatrix();
        return this;
      };
      Node.prototype.updateMatrix = function() {
        this.matrix.identity();
        for (var i = 0; i < this.transforms.length; i++) {
          this.transforms[i].apply(this.matrix);
        }
      };
      function Transform() {
        this.sid = "";
        this.type = "";
        this.data = [];
        this.obj = null;
      }
      Transform.prototype.parse = function(element) {
        this.sid = element.getAttribute('sid');
        this.type = element.nodeName;
        this.data = _floats(element.textContent);
        this.convert();
        return this;
      };
      Transform.prototype.convert = function() {
        switch (this.type) {
          case 'matrix':
            this.obj = getConvertedMat4(this.data);
            break;
          case 'rotate':
            this.angle = THREE.Math.degToRad(this.data[3]);
          case 'translate':
            fixCoords(this.data, -1);
            this.obj = new THREE.Vector3(this.data[0], this.data[1], this.data[2]);
            break;
          case 'scale':
            fixCoords(this.data, 1);
            this.obj = new THREE.Vector3(this.data[0], this.data[1], this.data[2]);
            break;
          default:
            console.log('Can not convert Transform of type ' + this.type);
            break;
        }
      };
      Transform.prototype.apply = function() {
        var m1 = new THREE.Matrix4();
        return function(matrix) {
          switch (this.type) {
            case 'matrix':
              matrix.multiply(this.obj);
              break;
            case 'translate':
              matrix.multiply(m1.makeTranslation(this.obj.x, this.obj.y, this.obj.z));
              break;
            case 'rotate':
              matrix.multiply(m1.makeRotationAxis(this.obj, this.angle));
              break;
            case 'scale':
              matrix.scale(this.obj);
              break;
          }
        };
      }();
      Transform.prototype.update = function(data, member) {
        var members = ['X', 'Y', 'Z', 'ANGLE'];
        switch (this.type) {
          case 'matrix':
            if (!member) {
              this.obj.copy(data);
            } else if (member.length === 1) {
              switch (member[0]) {
                case 0:
                  this.obj.n11 = data[0];
                  this.obj.n21 = data[1];
                  this.obj.n31 = data[2];
                  this.obj.n41 = data[3];
                  break;
                case 1:
                  this.obj.n12 = data[0];
                  this.obj.n22 = data[1];
                  this.obj.n32 = data[2];
                  this.obj.n42 = data[3];
                  break;
                case 2:
                  this.obj.n13 = data[0];
                  this.obj.n23 = data[1];
                  this.obj.n33 = data[2];
                  this.obj.n43 = data[3];
                  break;
                case 3:
                  this.obj.n14 = data[0];
                  this.obj.n24 = data[1];
                  this.obj.n34 = data[2];
                  this.obj.n44 = data[3];
                  break;
              }
            } else if (member.length === 2) {
              var propName = 'n' + (member[0] + 1) + (member[1] + 1);
              this.obj[propName] = data;
            } else {
              console.log('Incorrect addressing of matrix in transform.');
            }
            break;
          case 'translate':
          case 'scale':
            if (Object.prototype.toString.call(member) === '[object Array]') {
              member = members[member[0]];
            }
            switch (member) {
              case 'X':
                this.obj.x = data;
                break;
              case 'Y':
                this.obj.y = data;
                break;
              case 'Z':
                this.obj.z = data;
                break;
              default:
                this.obj.x = data[0];
                this.obj.y = data[1];
                this.obj.z = data[2];
                break;
            }
            break;
          case 'rotate':
            if (Object.prototype.toString.call(member) === '[object Array]') {
              member = members[member[0]];
            }
            switch (member) {
              case 'X':
                this.obj.x = data;
                break;
              case 'Y':
                this.obj.y = data;
                break;
              case 'Z':
                this.obj.z = data;
                break;
              case 'ANGLE':
                this.angle = THREE.Math.degToRad(data);
                break;
              default:
                this.obj.x = data[0];
                this.obj.y = data[1];
                this.obj.z = data[2];
                this.angle = THREE.Math.degToRad(data[3]);
                break;
            }
            break;
        }
      };
      function InstanceController() {
        this.url = "";
        this.skeleton = [];
        this.instance_material = [];
      }
      InstanceController.prototype.parse = function(element) {
        this.url = element.getAttribute('url').replace(/^#/, '');
        this.skeleton = [];
        this.instance_material = [];
        for (var i = 0; i < element.childNodes.length; i++) {
          var child = element.childNodes[i];
          if (child.nodeType !== 1)
            continue;
          switch (child.nodeName) {
            case 'skeleton':
              this.skeleton.push(child.textContent.replace(/^#/, ''));
              break;
            case 'bind_material':
              var instances = child.querySelectorAll('instance_material');
              for (var j = 0; j < instances.length; j++) {
                var instance = instances[j];
                this.instance_material.push((new InstanceMaterial()).parse(instance));
              }
              break;
            case 'extra':
              break;
            default:
              break;
          }
        }
        return this;
      };
      function InstanceMaterial() {
        this.symbol = "";
        this.target = "";
      }
      InstanceMaterial.prototype.parse = function(element) {
        this.symbol = element.getAttribute('symbol');
        this.target = element.getAttribute('target').replace(/^#/, '');
        return this;
      };
      function InstanceGeometry() {
        this.url = "";
        this.instance_material = [];
      }
      InstanceGeometry.prototype.parse = function(element) {
        this.url = element.getAttribute('url').replace(/^#/, '');
        this.instance_material = [];
        for (var i = 0; i < element.childNodes.length; i++) {
          var child = element.childNodes[i];
          if (child.nodeType != 1)
            continue;
          if (child.nodeName === 'bind_material') {
            var instances = child.querySelectorAll('instance_material');
            for (var j = 0; j < instances.length; j++) {
              var instance = instances[j];
              this.instance_material.push((new InstanceMaterial()).parse(instance));
            }
            break;
          }
        }
        return this;
      };
      function Geometry() {
        this.id = "";
        this.mesh = null;
      }
      Geometry.prototype.parse = function(element) {
        this.id = element.getAttribute('id');
        extractDoubleSided(this, element);
        for (var i = 0; i < element.childNodes.length; i++) {
          var child = element.childNodes[i];
          switch (child.nodeName) {
            case 'mesh':
              this.mesh = (new Mesh(this)).parse(child);
              break;
            case 'extra':
              break;
            default:
              break;
          }
        }
        return this;
      };
      function Mesh(geometry) {
        this.geometry = geometry.id;
        this.primitives = [];
        this.vertices = null;
        this.geometry3js = null;
      }
      Mesh.prototype.parse = function(element) {
        this.primitives = [];
        for (var i = 0; i < element.childNodes.length; i++) {
          var child = element.childNodes[i];
          switch (child.nodeName) {
            case 'source':
              _source(child);
              break;
            case 'vertices':
              this.vertices = (new Vertices()).parse(child);
              break;
            case 'linestrips':
              this.primitives.push((new LineStrips().parse(child)));
              break;
            case 'triangles':
              this.primitives.push((new Triangles().parse(child)));
              break;
            case 'polygons':
              this.primitives.push((new Polygons().parse(child)));
              break;
            case 'polylist':
              this.primitives.push((new Polylist().parse(child)));
              break;
            default:
              break;
          }
        }
        this.geometry3js = new THREE.Geometry();
        if (this.vertices === null) {
          return this;
        }
        var vertexData = sources[this.vertices.input['POSITION'].source].data;
        for (var i = 0; i < vertexData.length; i += 3) {
          this.geometry3js.vertices.push(getConvertedVec3(vertexData, i).clone());
        }
        for (var i = 0; i < this.primitives.length; i++) {
          var primitive = this.primitives[i];
          primitive.setVertices(this.vertices);
          this.handlePrimitive(primitive, this.geometry3js);
        }
        if (this.geometry3js.calcNormals) {
          this.geometry3js.computeVertexNormals();
          delete this.geometry3js.calcNormals;
        }
        return this;
      };
      Mesh.prototype.handlePrimitive = function(primitive, geom) {
        if (primitive instanceof LineStrips) {
          geom.isLineStrip = true;
          return;
        }
        var j,
            k,
            pList = primitive.p,
            inputs = primitive.inputs;
        var input,
            index,
            idx32;
        var source,
            numParams;
        var vcIndex = 0,
            vcount = 3,
            maxOffset = 0;
        var texture_sets = [];
        for (j = 0; j < inputs.length; j++) {
          input = inputs[j];
          var offset = input.offset + 1;
          maxOffset = (maxOffset < offset) ? offset : maxOffset;
          switch (input.semantic) {
            case 'TEXCOORD':
              texture_sets.push(input.set);
              break;
          }
        }
        for (var pCount = 0; pCount < pList.length; ++pCount) {
          var p = pList[pCount],
              i = 0;
          while (i < p.length) {
            var vs = [];
            var ns = [];
            var ts = null;
            var cs = [];
            if (primitive.vcount) {
              vcount = primitive.vcount.length ? primitive.vcount[vcIndex++] : primitive.vcount;
            } else {
              vcount = p.length / maxOffset;
            }
            for (j = 0; j < vcount; j++) {
              for (k = 0; k < inputs.length; k++) {
                input = inputs[k];
                source = sources[input.source];
                index = p[i + (j * maxOffset) + input.offset];
                numParams = source.accessor.params.length;
                idx32 = index * numParams;
                switch (input.semantic) {
                  case 'VERTEX':
                    vs.push(index);
                    break;
                  case 'NORMAL':
                    ns.push(getConvertedVec3(source.data, idx32));
                    break;
                  case 'TEXCOORD':
                    ts = ts || {};
                    if (ts[input.set] === undefined)
                      ts[input.set] = [];
                    ts[input.set].push(new THREE.Vector2(source.data[idx32], source.data[idx32 + 1]));
                    break;
                  case 'COLOR':
                    cs.push(new THREE.Color().setRGB(source.data[idx32], source.data[idx32 + 1], source.data[idx32 + 2]));
                    break;
                  default:
                    break;
                }
              }
            }
            if (ns.length === 0) {
              input = this.vertices.input.NORMAL;
              if (input) {
                source = sources[input.source];
                numParams = source.accessor.params.length;
                for (var ndx = 0,
                    len = vs.length; ndx < len; ndx++) {
                  ns.push(getConvertedVec3(source.data, vs[ndx] * numParams));
                }
              } else {
                geom.calcNormals = true;
              }
            }
            if (!ts) {
              ts = {};
              input = this.vertices.input.TEXCOORD;
              if (input) {
                texture_sets.push(input.set);
                source = sources[input.source];
                numParams = source.accessor.params.length;
                for (var ndx = 0,
                    len = vs.length; ndx < len; ndx++) {
                  idx32 = vs[ndx] * numParams;
                  if (ts[input.set] === undefined)
                    ts[input.set] = [];
                  ts[input.set].push(new THREE.Vector2(source.data[idx32], 1.0 - source.data[idx32 + 1]));
                }
              }
            }
            if (cs.length === 0) {
              input = this.vertices.input.COLOR;
              if (input) {
                source = sources[input.source];
                numParams = source.accessor.params.length;
                for (var ndx = 0,
                    len = vs.length; ndx < len; ndx++) {
                  idx32 = vs[ndx] * numParams;
                  cs.push(new THREE.Color().setRGB(source.data[idx32], source.data[idx32 + 1], source.data[idx32 + 2]));
                }
              }
            }
            var face = null,
                faces = [],
                uv,
                uvArr;
            if (vcount === 3) {
              faces.push(new THREE.Face3(vs[0], vs[1], vs[2], ns, cs.length ? cs : new THREE.Color()));
            } else if (vcount === 4) {
              faces.push(new THREE.Face3(vs[0], vs[1], vs[3], ns.length ? [ns[0].clone(), ns[1].clone(), ns[3].clone()] : [], cs.length ? [cs[0], cs[1], cs[3]] : new THREE.Color()));
              faces.push(new THREE.Face3(vs[1], vs[2], vs[3], ns.length ? [ns[1].clone(), ns[2].clone(), ns[3].clone()] : [], cs.length ? [cs[1], cs[2], cs[3]] : new THREE.Color()));
            } else if (vcount > 4 && options.subdivideFaces) {
              var clr = cs.length ? cs : new THREE.Color(),
                  vec1,
                  vec2,
                  vec3,
                  v1,
                  v2,
                  norm;
              for (k = 1; k < vcount - 1; ) {
                faces.push(new THREE.Face3(vs[0], vs[k], vs[k + 1], ns.length ? [ns[0].clone(), ns[k++].clone(), ns[k].clone()] : [], clr));
              }
            }
            if (faces.length) {
              for (var ndx = 0,
                  len = faces.length; ndx < len; ndx++) {
                face = faces[ndx];
                face.daeMaterial = primitive.material;
                geom.faces.push(face);
                for (k = 0; k < texture_sets.length; k++) {
                  uv = ts[texture_sets[k]];
                  if (vcount > 4) {
                    uvArr = [uv[0], uv[ndx + 1], uv[ndx + 2]];
                  } else if (vcount === 4) {
                    if (ndx === 0) {
                      uvArr = [uv[0], uv[1], uv[3]];
                    } else {
                      uvArr = [uv[1].clone(), uv[2], uv[3].clone()];
                    }
                  } else {
                    uvArr = [uv[0], uv[1], uv[2]];
                  }
                  if (geom.faceVertexUvs[k] === undefined) {
                    geom.faceVertexUvs[k] = [];
                  }
                  geom.faceVertexUvs[k].push(uvArr);
                }
              }
            } else {
              console.log('dropped face with vcount ' + vcount + ' for geometry with id: ' + geom.id);
            }
            i += maxOffset * vcount;
          }
        }
      };
      function Polygons() {
        this.material = "";
        this.count = 0;
        this.inputs = [];
        this.vcount = null;
        this.p = [];
        this.geometry = new THREE.Geometry();
      }
      Polygons.prototype.setVertices = function(vertices) {
        for (var i = 0; i < this.inputs.length; i++) {
          if (this.inputs[i].source === vertices.id) {
            this.inputs[i].source = vertices.input['POSITION'].source;
          }
        }
      };
      Polygons.prototype.parse = function(element) {
        this.material = element.getAttribute('material');
        this.count = _attr_as_int(element, 'count', 0);
        for (var i = 0; i < element.childNodes.length; i++) {
          var child = element.childNodes[i];
          switch (child.nodeName) {
            case 'input':
              this.inputs.push((new Input()).parse(element.childNodes[i]));
              break;
            case 'vcount':
              this.vcount = _ints(child.textContent);
              break;
            case 'p':
              this.p.push(_ints(child.textContent));
              break;
            case 'ph':
              console.warn('polygon holes not yet supported!');
              break;
            default:
              break;
          }
        }
        return this;
      };
      function Polylist() {
        Polygons.call(this);
        this.vcount = [];
      }
      Polylist.prototype = Object.create(Polygons.prototype);
      Polylist.prototype.constructor = Polylist;
      function LineStrips() {
        Polygons.call(this);
        this.vcount = 1;
      }
      LineStrips.prototype = Object.create(Polygons.prototype);
      LineStrips.prototype.constructor = LineStrips;
      function Triangles() {
        Polygons.call(this);
        this.vcount = 3;
      }
      Triangles.prototype = Object.create(Polygons.prototype);
      Triangles.prototype.constructor = Triangles;
      function Accessor() {
        this.source = "";
        this.count = 0;
        this.stride = 0;
        this.params = [];
      }
      Accessor.prototype.parse = function(element) {
        this.params = [];
        this.source = element.getAttribute('source');
        this.count = _attr_as_int(element, 'count', 0);
        this.stride = _attr_as_int(element, 'stride', 0);
        for (var i = 0; i < element.childNodes.length; i++) {
          var child = element.childNodes[i];
          if (child.nodeName === 'param') {
            var param = {};
            param['name'] = child.getAttribute('name');
            param['type'] = child.getAttribute('type');
            this.params.push(param);
          }
        }
        return this;
      };
      function Vertices() {
        this.input = {};
      }
      Vertices.prototype.parse = function(element) {
        this.id = element.getAttribute('id');
        for (var i = 0; i < element.childNodes.length; i++) {
          if (element.childNodes[i].nodeName === 'input') {
            var input = (new Input()).parse(element.childNodes[i]);
            this.input[input.semantic] = input;
          }
        }
        return this;
      };
      function Input() {
        this.semantic = "";
        this.offset = 0;
        this.source = "";
        this.set = 0;
      }
      Input.prototype.parse = function(element) {
        this.semantic = element.getAttribute('semantic');
        this.source = element.getAttribute('source').replace(/^#/, '');
        this.set = _attr_as_int(element, 'set', -1);
        this.offset = _attr_as_int(element, 'offset', 0);
        if (this.semantic === 'TEXCOORD' && this.set < 0) {
          this.set = 0;
        }
        return this;
      };
      function Source(id) {
        this.id = id;
        this.type = null;
      }
      Source.prototype.parse = function(element) {
        this.id = element.getAttribute('id');
        for (var i = 0; i < element.childNodes.length; i++) {
          var child = element.childNodes[i];
          switch (child.nodeName) {
            case 'bool_array':
              this.data = _bools(child.textContent);
              this.type = child.nodeName;
              break;
            case 'float_array':
              this.data = _floats(child.textContent);
              this.type = child.nodeName;
              break;
            case 'int_array':
              this.data = _ints(child.textContent);
              this.type = child.nodeName;
              break;
            case 'IDREF_array':
            case 'Name_array':
              this.data = _strings(child.textContent);
              this.type = child.nodeName;
              break;
            case 'technique_common':
              for (var j = 0; j < child.childNodes.length; j++) {
                if (child.childNodes[j].nodeName === 'accessor') {
                  this.accessor = (new Accessor()).parse(child.childNodes[j]);
                  break;
                }
              }
              break;
            default:
              break;
          }
        }
        return this;
      };
      Source.prototype.read = function() {
        var result = [];
        var param = this.accessor.params[0];
        switch (param.type) {
          case 'IDREF':
          case 'Name':
          case 'name':
          case 'float':
            return this.data;
          case 'float4x4':
            for (var j = 0; j < this.data.length; j += 16) {
              var s = this.data.slice(j, j + 16);
              var m = getConvertedMat4(s);
              result.push(m);
            }
            break;
          default:
            console.log('ColladaLoader: Source: Read dont know how to read ' + param.type + '.');
            break;
        }
        return result;
      };
      function Material() {
        this.id = "";
        this.name = "";
        this.instance_effect = null;
      }
      Material.prototype.parse = function(element) {
        this.id = element.getAttribute('id');
        this.name = element.getAttribute('name');
        for (var i = 0; i < element.childNodes.length; i++) {
          if (element.childNodes[i].nodeName === 'instance_effect') {
            this.instance_effect = (new InstanceEffect()).parse(element.childNodes[i]);
            break;
          }
        }
        return this;
      };
      function ColorOrTexture() {
        this.color = new THREE.Color();
        this.color.setRGB(Math.random(), Math.random(), Math.random());
        this.color.a = 1.0;
        this.texture = null;
        this.texcoord = null;
        this.texOpts = null;
      }
      ColorOrTexture.prototype.isColor = function() {
        return (this.texture === null);
      };
      ColorOrTexture.prototype.isTexture = function() {
        return (this.texture != null);
      };
      ColorOrTexture.prototype.parse = function(element) {
        if (element.nodeName === 'transparent') {
          this.opaque = element.getAttribute('opaque');
        }
        for (var i = 0; i < element.childNodes.length; i++) {
          var child = element.childNodes[i];
          if (child.nodeType != 1)
            continue;
          switch (child.nodeName) {
            case 'color':
              var rgba = _floats(child.textContent);
              this.color = new THREE.Color();
              this.color.setRGB(rgba[0], rgba[1], rgba[2]);
              this.color.a = rgba[3];
              break;
            case 'texture':
              this.texture = child.getAttribute('texture');
              this.texcoord = child.getAttribute('texcoord');
              this.texOpts = {
                offsetU: 0,
                offsetV: 0,
                repeatU: 1,
                repeatV: 1,
                wrapU: 1,
                wrapV: 1
              };
              this.parseTexture(child);
              break;
            default:
              break;
          }
        }
        return this;
      };
      ColorOrTexture.prototype.parseTexture = function(element) {
        if (!element.childNodes)
          return this;
        if (element.childNodes[1] && element.childNodes[1].nodeName === 'extra') {
          element = element.childNodes[1];
          if (element.childNodes[1] && element.childNodes[1].nodeName === 'technique') {
            element = element.childNodes[1];
          }
        }
        for (var i = 0; i < element.childNodes.length; i++) {
          var child = element.childNodes[i];
          switch (child.nodeName) {
            case 'offsetU':
            case 'offsetV':
            case 'repeatU':
            case 'repeatV':
              this.texOpts[child.nodeName] = parseFloat(child.textContent);
              break;
            case 'wrapU':
            case 'wrapV':
              if (child.textContent.toUpperCase() === 'TRUE') {
                this.texOpts[child.nodeName] = 1;
              } else {
                this.texOpts[child.nodeName] = parseInt(child.textContent);
              }
              break;
            default:
              this.texOpts[child.nodeName] = child.textContent;
              break;
          }
        }
        return this;
      };
      function Shader(type, effect) {
        this.type = type;
        this.effect = effect;
        this.material = null;
      }
      Shader.prototype.parse = function(element) {
        for (var i = 0; i < element.childNodes.length; i++) {
          var child = element.childNodes[i];
          if (child.nodeType != 1)
            continue;
          switch (child.nodeName) {
            case 'emission':
            case 'diffuse':
            case 'specular':
            case 'transparent':
              this[child.nodeName] = (new ColorOrTexture()).parse(child);
              break;
            case 'bump':
              var bumpType = child.getAttribute('bumptype');
              if (bumpType) {
                if (bumpType.toLowerCase() === "heightfield") {
                  this['bump'] = (new ColorOrTexture()).parse(child);
                } else if (bumpType.toLowerCase() === "normalmap") {
                  this['normal'] = (new ColorOrTexture()).parse(child);
                } else {
                  console.error("Shader.prototype.parse: Invalid value for attribute 'bumptype' (" + bumpType + ") - valid bumptypes are 'HEIGHTFIELD' and 'NORMALMAP' - defaulting to 'HEIGHTFIELD'");
                  this['bump'] = (new ColorOrTexture()).parse(child);
                }
              } else {
                console.warn("Shader.prototype.parse: Attribute 'bumptype' missing from bump node - defaulting to 'HEIGHTFIELD'");
                this['bump'] = (new ColorOrTexture()).parse(child);
              }
              break;
            case 'shininess':
            case 'reflectivity':
            case 'index_of_refraction':
            case 'transparency':
              var f = child.querySelectorAll('float');
              if (f.length > 0)
                this[child.nodeName] = parseFloat(f[0].textContent);
              break;
            default:
              break;
          }
        }
        this.create();
        return this;
      };
      Shader.prototype.create = function() {
        var props = {};
        var transparent = false;
        if (this['transparency'] !== undefined && this['transparent'] !== undefined) {
          var transparentColor = this['transparent'];
          var transparencyLevel = (this.transparent.color.r + this.transparent.color.g + this.transparent.color.b) / 3 * this.transparency;
          if (transparencyLevel > 0) {
            transparent = true;
            props['transparent'] = true;
            props['opacity'] = 1 - transparencyLevel;
          }
        }
        var keys = {
          'diffuse': 'map',
          'ambient': 'lightMap',
          'specular': 'specularMap',
          'emission': 'emissionMap',
          'bump': 'bumpMap',
          'normal': 'normalMap'
        };
        for (var prop in this) {
          switch (prop) {
            case 'ambient':
            case 'emission':
            case 'diffuse':
            case 'specular':
            case 'bump':
            case 'normal':
              var cot = this[prop];
              if (cot instanceof ColorOrTexture) {
                if (cot.isTexture()) {
                  var samplerId = cot.texture;
                  var surfaceId = this.effect.sampler[samplerId];
                  if (surfaceId !== undefined && surfaceId.source !== undefined) {
                    var surface = this.effect.surface[surfaceId.source];
                    if (surface !== undefined) {
                      var image = images[surface.init_from];
                      if (image) {
                        var url = baseUrl + image.init_from;
                        var texture;
                        var loader = THREE.Loader.Handlers.get(url);
                        if (loader !== null) {
                          texture = loader.load(url);
                        } else {
                          texture = new THREE.Texture();
                          loadTextureImage(texture, url);
                        }
                        texture.wrapS = cot.texOpts.wrapU ? THREE.RepeatWrapping : THREE.ClampToEdgeWrapping;
                        texture.wrapT = cot.texOpts.wrapV ? THREE.RepeatWrapping : THREE.ClampToEdgeWrapping;
                        texture.offset.x = cot.texOpts.offsetU;
                        texture.offset.y = cot.texOpts.offsetV;
                        texture.repeat.x = cot.texOpts.repeatU;
                        texture.repeat.y = cot.texOpts.repeatV;
                        props[keys[prop]] = texture;
                        if (prop === 'emission')
                          props['emissive'] = 0xffffff;
                      }
                    }
                  }
                } else if (prop === 'diffuse' || !transparent) {
                  if (prop === 'emission') {
                    props['emissive'] = cot.color.getHex();
                  } else {
                    props[prop] = cot.color.getHex();
                  }
                }
              }
              break;
            case 'shininess':
              props[prop] = this[prop];
              break;
            case 'reflectivity':
              props[prop] = this[prop];
              if (props[prop] > 0.0)
                props['envMap'] = options.defaultEnvMap;
              props['combine'] = THREE.MixOperation;
              break;
            case 'index_of_refraction':
              props['refractionRatio'] = this[prop];
              if (this[prop] !== 1.0)
                props['envMap'] = options.defaultEnvMap;
              break;
            case 'transparency':
              break;
            default:
              break;
          }
        }
        props['shading'] = preferredShading;
        props['side'] = this.effect.doubleSided ? THREE.DoubleSide : THREE.FrontSide;
        if (props.diffuse !== undefined) {
          props.color = props.diffuse;
          delete props.diffuse;
        }
        switch (this.type) {
          case 'constant':
            if (props.emissive != undefined)
              props.color = props.emissive;
            this.material = new THREE.MeshBasicMaterial(props);
            break;
          case 'phong':
          case 'blinn':
            this.material = new THREE.MeshPhongMaterial(props);
            break;
          case 'lambert':
          default:
            this.material = new THREE.MeshLambertMaterial(props);
            break;
        }
        return this.material;
      };
      function Surface(effect) {
        this.effect = effect;
        this.init_from = null;
        this.format = null;
      }
      Surface.prototype.parse = function(element) {
        for (var i = 0; i < element.childNodes.length; i++) {
          var child = element.childNodes[i];
          if (child.nodeType != 1)
            continue;
          switch (child.nodeName) {
            case 'init_from':
              this.init_from = child.textContent;
              break;
            case 'format':
              this.format = child.textContent;
              break;
            default:
              console.log("unhandled Surface prop: " + child.nodeName);
              break;
          }
        }
        return this;
      };
      function Sampler2D(effect) {
        this.effect = effect;
        this.source = null;
        this.wrap_s = null;
        this.wrap_t = null;
        this.minfilter = null;
        this.magfilter = null;
        this.mipfilter = null;
      }
      Sampler2D.prototype.parse = function(element) {
        for (var i = 0; i < element.childNodes.length; i++) {
          var child = element.childNodes[i];
          if (child.nodeType != 1)
            continue;
          switch (child.nodeName) {
            case 'source':
              this.source = child.textContent;
              break;
            case 'minfilter':
              this.minfilter = child.textContent;
              break;
            case 'magfilter':
              this.magfilter = child.textContent;
              break;
            case 'mipfilter':
              this.mipfilter = child.textContent;
              break;
            case 'wrap_s':
              this.wrap_s = child.textContent;
              break;
            case 'wrap_t':
              this.wrap_t = child.textContent;
              break;
            default:
              console.log("unhandled Sampler2D prop: " + child.nodeName);
              break;
          }
        }
        return this;
      };
      function Effect() {
        this.id = "";
        this.name = "";
        this.shader = null;
        this.surface = {};
        this.sampler = {};
      }
      Effect.prototype.create = function() {
        if (this.shader === null) {
          return null;
        }
      };
      Effect.prototype.parse = function(element) {
        this.id = element.getAttribute('id');
        this.name = element.getAttribute('name');
        extractDoubleSided(this, element);
        this.shader = null;
        for (var i = 0; i < element.childNodes.length; i++) {
          var child = element.childNodes[i];
          if (child.nodeType != 1)
            continue;
          switch (child.nodeName) {
            case 'profile_COMMON':
              this.parseTechnique(this.parseProfileCOMMON(child));
              break;
            default:
              break;
          }
        }
        return this;
      };
      Effect.prototype.parseNewparam = function(element) {
        var sid = element.getAttribute('sid');
        for (var i = 0; i < element.childNodes.length; i++) {
          var child = element.childNodes[i];
          if (child.nodeType != 1)
            continue;
          switch (child.nodeName) {
            case 'surface':
              this.surface[sid] = (new Surface(this)).parse(child);
              break;
            case 'sampler2D':
              this.sampler[sid] = (new Sampler2D(this)).parse(child);
              break;
            case 'extra':
              break;
            default:
              console.log(child.nodeName);
              break;
          }
        }
      };
      Effect.prototype.parseProfileCOMMON = function(element) {
        var technique;
        for (var i = 0; i < element.childNodes.length; i++) {
          var child = element.childNodes[i];
          if (child.nodeType != 1)
            continue;
          switch (child.nodeName) {
            case 'profile_COMMON':
              this.parseProfileCOMMON(child);
              break;
            case 'technique':
              technique = child;
              break;
            case 'newparam':
              this.parseNewparam(child);
              break;
            case 'image':
              var _image = (new _Image()).parse(child);
              images[_image.id] = _image;
              break;
            case 'extra':
              break;
            default:
              console.log(child.nodeName);
              break;
          }
        }
        return technique;
      };
      Effect.prototype.parseTechnique = function(element) {
        for (var i = 0; i < element.childNodes.length; i++) {
          var child = element.childNodes[i];
          if (child.nodeType != 1)
            continue;
          switch (child.nodeName) {
            case 'constant':
            case 'lambert':
            case 'blinn':
            case 'phong':
              this.shader = (new Shader(child.nodeName, this)).parse(child);
              break;
            case 'extra':
              this.parseExtra(child);
              break;
            default:
              break;
          }
        }
      };
      Effect.prototype.parseExtra = function(element) {
        for (var i = 0; i < element.childNodes.length; i++) {
          var child = element.childNodes[i];
          if (child.nodeType != 1)
            continue;
          switch (child.nodeName) {
            case 'technique':
              this.parseExtraTechnique(child);
              break;
            default:
              break;
          }
        }
      };
      Effect.prototype.parseExtraTechnique = function(element) {
        for (var i = 0; i < element.childNodes.length; i++) {
          var child = element.childNodes[i];
          if (child.nodeType != 1)
            continue;
          switch (child.nodeName) {
            case 'bump':
              this.shader.parse(element);
              break;
            default:
              break;
          }
        }
      };
      function InstanceEffect() {
        this.url = "";
      }
      InstanceEffect.prototype.parse = function(element) {
        this.url = element.getAttribute('url').replace(/^#/, '');
        return this;
      };
      function Animation() {
        this.id = "";
        this.name = "";
        this.source = {};
        this.sampler = [];
        this.channel = [];
      }
      Animation.prototype.parse = function(element) {
        this.id = element.getAttribute('id');
        this.name = element.getAttribute('name');
        this.source = {};
        for (var i = 0; i < element.childNodes.length; i++) {
          var child = element.childNodes[i];
          if (child.nodeType != 1)
            continue;
          switch (child.nodeName) {
            case 'animation':
              var anim = (new Animation()).parse(child);
              for (var src in anim.source) {
                this.source[src] = anim.source[src];
              }
              for (var j = 0; j < anim.channel.length; j++) {
                this.channel.push(anim.channel[j]);
                this.sampler.push(anim.sampler[j]);
              }
              break;
            case 'source':
              var src = (new Source()).parse(child);
              this.source[src.id] = src;
              break;
            case 'sampler':
              this.sampler.push((new Sampler(this)).parse(child));
              break;
            case 'channel':
              this.channel.push((new Channel(this)).parse(child));
              break;
            default:
              break;
          }
        }
        return this;
      };
      function Channel(animation) {
        this.animation = animation;
        this.source = "";
        this.target = "";
        this.fullSid = null;
        this.sid = null;
        this.dotSyntax = null;
        this.arrSyntax = null;
        this.arrIndices = null;
        this.member = null;
      }
      Channel.prototype.parse = function(element) {
        this.source = element.getAttribute('source').replace(/^#/, '');
        this.target = element.getAttribute('target');
        var parts = this.target.split('/');
        var id = parts.shift();
        var sid = parts.shift();
        var dotSyntax = (sid.indexOf(".") >= 0);
        var arrSyntax = (sid.indexOf("(") >= 0);
        if (dotSyntax) {
          parts = sid.split(".");
          this.sid = parts.shift();
          this.member = parts.shift();
        } else if (arrSyntax) {
          var arrIndices = sid.split("(");
          this.sid = arrIndices.shift();
          for (var j = 0; j < arrIndices.length; j++) {
            arrIndices[j] = parseInt(arrIndices[j].replace(/\)/, ''));
          }
          this.arrIndices = arrIndices;
        } else {
          this.sid = sid;
        }
        this.fullSid = sid;
        this.dotSyntax = dotSyntax;
        this.arrSyntax = arrSyntax;
        return this;
      };
      function Sampler(animation) {
        this.id = "";
        this.animation = animation;
        this.inputs = [];
        this.input = null;
        this.output = null;
        this.strideOut = null;
        this.interpolation = null;
        this.startTime = null;
        this.endTime = null;
        this.duration = 0;
      }
      Sampler.prototype.parse = function(element) {
        this.id = element.getAttribute('id');
        this.inputs = [];
        for (var i = 0; i < element.childNodes.length; i++) {
          var child = element.childNodes[i];
          if (child.nodeType != 1)
            continue;
          switch (child.nodeName) {
            case 'input':
              this.inputs.push((new Input()).parse(child));
              break;
            default:
              break;
          }
        }
        return this;
      };
      Sampler.prototype.create = function() {
        for (var i = 0; i < this.inputs.length; i++) {
          var input = this.inputs[i];
          var source = this.animation.source[input.source];
          switch (input.semantic) {
            case 'INPUT':
              this.input = source.read();
              break;
            case 'OUTPUT':
              this.output = source.read();
              this.strideOut = source.accessor.stride;
              break;
            case 'INTERPOLATION':
              this.interpolation = source.read();
              break;
            case 'IN_TANGENT':
              break;
            case 'OUT_TANGENT':
              break;
            default:
              console.log(input.semantic);
              break;
          }
        }
        this.startTime = 0;
        this.endTime = 0;
        this.duration = 0;
        if (this.input.length) {
          this.startTime = 100000000;
          this.endTime = -100000000;
          for (var i = 0; i < this.input.length; i++) {
            this.startTime = Math.min(this.startTime, this.input[i]);
            this.endTime = Math.max(this.endTime, this.input[i]);
          }
          this.duration = this.endTime - this.startTime;
        }
      };
      Sampler.prototype.getData = function(type, ndx, member) {
        var data;
        if (type === 'matrix' && this.strideOut === 16) {
          data = this.output[ndx];
        } else if (this.strideOut > 1) {
          data = [];
          ndx *= this.strideOut;
          for (var i = 0; i < this.strideOut; ++i) {
            data[i] = this.output[ndx + i];
          }
          if (this.strideOut === 3) {
            switch (type) {
              case 'rotate':
              case 'translate':
                fixCoords(data, -1);
                break;
              case 'scale':
                fixCoords(data, 1);
                break;
            }
          } else if (this.strideOut === 4 && type === 'matrix') {
            fixCoords(data, -1);
          }
        } else {
          data = this.output[ndx];
          if (member && type === 'translate') {
            data = getConvertedTranslation(member, data);
          }
        }
        return data;
      };
      function Key(time) {
        this.targets = [];
        this.time = time;
      }
      Key.prototype.addTarget = function(fullSid, transform, member, data) {
        this.targets.push({
          sid: fullSid,
          member: member,
          transform: transform,
          data: data
        });
      };
      Key.prototype.apply = function(opt_sid) {
        for (var i = 0; i < this.targets.length; ++i) {
          var target = this.targets[i];
          if (!opt_sid || target.sid === opt_sid) {
            target.transform.update(target.data, target.member);
          }
        }
      };
      Key.prototype.getTarget = function(fullSid) {
        for (var i = 0; i < this.targets.length; ++i) {
          if (this.targets[i].sid === fullSid) {
            return this.targets[i];
          }
        }
        return null;
      };
      Key.prototype.hasTarget = function(fullSid) {
        for (var i = 0; i < this.targets.length; ++i) {
          if (this.targets[i].sid === fullSid) {
            return true;
          }
        }
        return false;
      };
      Key.prototype.interpolate = function(nextKey, time) {
        for (var i = 0,
            l = this.targets.length; i < l; i++) {
          var target = this.targets[i],
              nextTarget = nextKey.getTarget(target.sid),
              data;
          if (target.transform.type !== 'matrix' && nextTarget) {
            var scale = (time - this.time) / (nextKey.time - this.time),
                nextData = nextTarget.data,
                prevData = target.data;
            if (scale < 0)
              scale = 0;
            if (scale > 1)
              scale = 1;
            if (prevData.length) {
              data = [];
              for (var j = 0; j < prevData.length; ++j) {
                data[j] = prevData[j] + (nextData[j] - prevData[j]) * scale;
              }
            } else {
              data = prevData + (nextData - prevData) * scale;
            }
          } else {
            data = target.data;
          }
          target.transform.update(data, target.member);
        }
      };
      function Camera() {
        this.id = "";
        this.name = "";
        this.technique = "";
      }
      Camera.prototype.parse = function(element) {
        this.id = element.getAttribute('id');
        this.name = element.getAttribute('name');
        for (var i = 0; i < element.childNodes.length; i++) {
          var child = element.childNodes[i];
          if (child.nodeType != 1)
            continue;
          switch (child.nodeName) {
            case 'optics':
              this.parseOptics(child);
              break;
            default:
              break;
          }
        }
        return this;
      };
      Camera.prototype.parseOptics = function(element) {
        for (var i = 0; i < element.childNodes.length; i++) {
          if (element.childNodes[i].nodeName === 'technique_common') {
            var technique = element.childNodes[i];
            for (var j = 0; j < technique.childNodes.length; j++) {
              this.technique = technique.childNodes[j].nodeName;
              if (this.technique === 'perspective') {
                var perspective = technique.childNodes[j];
                for (var k = 0; k < perspective.childNodes.length; k++) {
                  var param = perspective.childNodes[k];
                  switch (param.nodeName) {
                    case 'yfov':
                      this.yfov = param.textContent;
                      break;
                    case 'xfov':
                      this.xfov = param.textContent;
                      break;
                    case 'znear':
                      this.znear = param.textContent;
                      break;
                    case 'zfar':
                      this.zfar = param.textContent;
                      break;
                    case 'aspect_ratio':
                      this.aspect_ratio = param.textContent;
                      break;
                  }
                }
              } else if (this.technique === 'orthographic') {
                var orthographic = technique.childNodes[j];
                for (var k = 0; k < orthographic.childNodes.length; k++) {
                  var param = orthographic.childNodes[k];
                  switch (param.nodeName) {
                    case 'xmag':
                      this.xmag = param.textContent;
                      break;
                    case 'ymag':
                      this.ymag = param.textContent;
                      break;
                    case 'znear':
                      this.znear = param.textContent;
                      break;
                    case 'zfar':
                      this.zfar = param.textContent;
                      break;
                    case 'aspect_ratio':
                      this.aspect_ratio = param.textContent;
                      break;
                  }
                }
              }
            }
          }
        }
        return this;
      };
      function InstanceCamera() {
        this.url = "";
      }
      InstanceCamera.prototype.parse = function(element) {
        this.url = element.getAttribute('url').replace(/^#/, '');
        return this;
      };
      function Light() {
        this.id = "";
        this.name = "";
        this.technique = "";
      }
      Light.prototype.parse = function(element) {
        this.id = element.getAttribute('id');
        this.name = element.getAttribute('name');
        for (var i = 0; i < element.childNodes.length; i++) {
          var child = element.childNodes[i];
          if (child.nodeType != 1)
            continue;
          switch (child.nodeName) {
            case 'technique_common':
              this.parseCommon(child);
              break;
            case 'technique':
              this.parseTechnique(child);
              break;
            default:
              break;
          }
        }
        return this;
      };
      Light.prototype.parseCommon = function(element) {
        for (var i = 0; i < element.childNodes.length; i++) {
          switch (element.childNodes[i].nodeName) {
            case 'directional':
            case 'point':
            case 'spot':
            case 'ambient':
              this.technique = element.childNodes[i].nodeName;
              var light = element.childNodes[i];
              for (var j = 0; j < light.childNodes.length; j++) {
                var child = light.childNodes[j];
                switch (child.nodeName) {
                  case 'color':
                    var rgba = _floats(child.textContent);
                    this.color = new THREE.Color(0);
                    this.color.setRGB(rgba[0], rgba[1], rgba[2]);
                    this.color.a = rgba[3];
                    break;
                  case 'falloff_angle':
                    this.falloff_angle = parseFloat(child.textContent);
                    break;
                  case 'quadratic_attenuation':
                    var f = parseFloat(child.textContent);
                    this.distance = f ? Math.sqrt(1 / f) : 0;
                }
              }
          }
        }
        return this;
      };
      Light.prototype.parseTechnique = function(element) {
        this.profile = element.getAttribute('profile');
        for (var i = 0; i < element.childNodes.length; i++) {
          var child = element.childNodes[i];
          switch (child.nodeName) {
            case 'intensity':
              this.intensity = parseFloat(child.textContent);
              break;
          }
        }
        return this;
      };
      function InstanceLight() {
        this.url = "";
      }
      InstanceLight.prototype.parse = function(element) {
        this.url = element.getAttribute('url').replace(/^#/, '');
        return this;
      };
      function KinematicsModel() {
        this.id = '';
        this.name = '';
        this.joints = [];
        this.links = [];
      }
      KinematicsModel.prototype.parse = function(element) {
        this.id = element.getAttribute('id');
        this.name = element.getAttribute('name');
        this.joints = [];
        this.links = [];
        for (var i = 0; i < element.childNodes.length; i++) {
          var child = element.childNodes[i];
          if (child.nodeType != 1)
            continue;
          switch (child.nodeName) {
            case 'technique_common':
              this.parseCommon(child);
              break;
            default:
              break;
          }
        }
        return this;
      };
      KinematicsModel.prototype.parseCommon = function(element) {
        for (var i = 0; i < element.childNodes.length; i++) {
          var child = element.childNodes[i];
          if (child.nodeType != 1)
            continue;
          switch (element.childNodes[i].nodeName) {
            case 'joint':
              this.joints.push((new Joint()).parse(child));
              break;
            case 'link':
              this.links.push((new Link()).parse(child));
              break;
            default:
              break;
          }
        }
        return this;
      };
      function Joint() {
        this.sid = '';
        this.name = '';
        this.axis = new THREE.Vector3();
        this.limits = {
          min: 0,
          max: 0
        };
        this.type = '';
        this.static = false;
        this.zeroPosition = 0.0;
        this.middlePosition = 0.0;
      }
      Joint.prototype.parse = function(element) {
        this.sid = element.getAttribute('sid');
        this.name = element.getAttribute('name');
        this.axis = new THREE.Vector3();
        this.limits = {
          min: 0,
          max: 0
        };
        this.type = '';
        this.static = false;
        this.zeroPosition = 0.0;
        this.middlePosition = 0.0;
        var axisElement = element.querySelector('axis');
        var _axis = _floats(axisElement.textContent);
        this.axis = getConvertedVec3(_axis, 0);
        var min = element.querySelector('limits min') ? parseFloat(element.querySelector('limits min').textContent) : -360;
        var max = element.querySelector('limits max') ? parseFloat(element.querySelector('limits max').textContent) : 360;
        this.limits = {
          min: min,
          max: max
        };
        var jointTypes = ['prismatic', 'revolute'];
        for (var i = 0; i < jointTypes.length; i++) {
          var type = jointTypes[i];
          var jointElement = element.querySelector(type);
          if (jointElement) {
            this.type = type;
          }
        }
        if (this.limits.min >= this.limits.max) {
          this.static = true;
        }
        this.middlePosition = (this.limits.min + this.limits.max) / 2.0;
        return this;
      };
      function Link() {
        this.sid = '';
        this.name = '';
        this.transforms = [];
        this.attachments = [];
      }
      Link.prototype.parse = function(element) {
        this.sid = element.getAttribute('sid');
        this.name = element.getAttribute('name');
        this.transforms = [];
        this.attachments = [];
        for (var i = 0; i < element.childNodes.length; i++) {
          var child = element.childNodes[i];
          if (child.nodeType != 1)
            continue;
          switch (child.nodeName) {
            case 'attachment_full':
              this.attachments.push((new Attachment()).parse(child));
              break;
            case 'rotate':
            case 'translate':
            case 'matrix':
              this.transforms.push((new Transform()).parse(child));
              break;
            default:
              break;
          }
        }
        return this;
      };
      function Attachment() {
        this.joint = '';
        this.transforms = [];
        this.links = [];
      }
      Attachment.prototype.parse = function(element) {
        this.joint = element.getAttribute('joint').split('/').pop();
        this.links = [];
        for (var i = 0; i < element.childNodes.length; i++) {
          var child = element.childNodes[i];
          if (child.nodeType != 1)
            continue;
          switch (child.nodeName) {
            case 'link':
              this.links.push((new Link()).parse(child));
              break;
            case 'rotate':
            case 'translate':
            case 'matrix':
              this.transforms.push((new Transform()).parse(child));
              break;
            default:
              break;
          }
        }
        return this;
      };
      function _source(element) {
        var id = element.getAttribute('id');
        if (sources[id] != undefined) {
          return sources[id];
        }
        sources[id] = (new Source(id)).parse(element);
        return sources[id];
      }
      function _nsResolver(nsPrefix) {
        if (nsPrefix === "dae") {
          return "http://www.collada.org/2005/11/COLLADASchema";
        }
        return null;
      }
      function _bools(str) {
        var raw = _strings(str);
        var data = [];
        for (var i = 0,
            l = raw.length; i < l; i++) {
          data.push((raw[i] === 'true' || raw[i] === '1') ? true : false);
        }
        return data;
      }
      function _floats(str) {
        var raw = _strings(str);
        var data = [];
        for (var i = 0,
            l = raw.length; i < l; i++) {
          data.push(parseFloat(raw[i]));
        }
        return data;
      }
      function _ints(str) {
        var raw = _strings(str);
        var data = [];
        for (var i = 0,
            l = raw.length; i < l; i++) {
          data.push(parseInt(raw[i], 10));
        }
        return data;
      }
      function _strings(str) {
        return (str.length > 0) ? _trimString(str).split(/\s+/) : [];
      }
      function _trimString(str) {
        return str.replace(/^\s+/, "").replace(/\s+$/, "");
      }
      function _attr_as_float(element, name, defaultValue) {
        if (element.hasAttribute(name)) {
          return parseFloat(element.getAttribute(name));
        } else {
          return defaultValue;
        }
      }
      function _attr_as_int(element, name, defaultValue) {
        if (element.hasAttribute(name)) {
          return parseInt(element.getAttribute(name), 10);
        } else {
          return defaultValue;
        }
      }
      function _attr_as_string(element, name, defaultValue) {
        if (element.hasAttribute(name)) {
          return element.getAttribute(name);
        } else {
          return defaultValue;
        }
      }
      function _format_float(f, num) {
        if (f === undefined) {
          var s = '0.';
          while (s.length < num + 2) {
            s += '0';
          }
          return s;
        }
        num = num || 2;
        var parts = f.toString().split('.');
        parts[1] = parts.length > 1 ? parts[1].substr(0, num) : "0";
        while (parts[1].length < num) {
          parts[1] += '0';
        }
        return parts.join('.');
      }
      function loadTextureImage(texture, url) {
        var loader = new THREE.ImageLoader();
        loader.load(url, function(image) {
          texture.image = image;
          texture.needsUpdate = true;
        });
      }
      function extractDoubleSided(obj, element) {
        obj.doubleSided = false;
        var node = element.querySelectorAll('extra double_sided')[0];
        if (node) {
          if (node && parseInt(node.textContent, 10) === 1) {
            obj.doubleSided = true;
          }
        }
      }
      function setUpConversion() {
        if (options.convertUpAxis !== true || colladaUp === options.upAxis) {
          upConversion = null;
        } else {
          switch (colladaUp) {
            case 'X':
              upConversion = options.upAxis === 'Y' ? 'XtoY' : 'XtoZ';
              break;
            case 'Y':
              upConversion = options.upAxis === 'X' ? 'YtoX' : 'YtoZ';
              break;
            case 'Z':
              upConversion = options.upAxis === 'X' ? 'ZtoX' : 'ZtoY';
              break;
          }
        }
      }
      function fixCoords(data, sign) {
        if (options.convertUpAxis !== true || colladaUp === options.upAxis) {
          return;
        }
        switch (upConversion) {
          case 'XtoY':
            var tmp = data[0];
            data[0] = sign * data[1];
            data[1] = tmp;
            break;
          case 'XtoZ':
            var tmp = data[2];
            data[2] = data[1];
            data[1] = data[0];
            data[0] = tmp;
            break;
          case 'YtoX':
            var tmp = data[0];
            data[0] = data[1];
            data[1] = sign * tmp;
            break;
          case 'YtoZ':
            var tmp = data[1];
            data[1] = sign * data[2];
            data[2] = tmp;
            break;
          case 'ZtoX':
            var tmp = data[0];
            data[0] = data[1];
            data[1] = data[2];
            data[2] = tmp;
            break;
          case 'ZtoY':
            var tmp = data[1];
            data[1] = data[2];
            data[2] = sign * tmp;
            break;
        }
      }
      function getConvertedTranslation(axis, data) {
        if (options.convertUpAxis !== true || colladaUp === options.upAxis) {
          return data;
        }
        switch (axis) {
          case 'X':
            data = upConversion === 'XtoY' ? data * -1 : data;
            break;
          case 'Y':
            data = upConversion === 'YtoZ' || upConversion === 'YtoX' ? data * -1 : data;
            break;
          case 'Z':
            data = upConversion === 'ZtoY' ? data * -1 : data;
            break;
          default:
            break;
        }
        return data;
      }
      function getConvertedVec3(data, offset) {
        var arr = [data[offset], data[offset + 1], data[offset + 2]];
        fixCoords(arr, -1);
        return new THREE.Vector3(arr[0], arr[1], arr[2]);
      }
      function getConvertedMat4(data) {
        if (options.convertUpAxis) {
          var arr = [data[0], data[4], data[8]];
          fixCoords(arr, -1);
          data[0] = arr[0];
          data[4] = arr[1];
          data[8] = arr[2];
          arr = [data[1], data[5], data[9]];
          fixCoords(arr, -1);
          data[1] = arr[0];
          data[5] = arr[1];
          data[9] = arr[2];
          arr = [data[2], data[6], data[10]];
          fixCoords(arr, -1);
          data[2] = arr[0];
          data[6] = arr[1];
          data[10] = arr[2];
          arr = [data[0], data[1], data[2]];
          fixCoords(arr, -1);
          data[0] = arr[0];
          data[1] = arr[1];
          data[2] = arr[2];
          arr = [data[4], data[5], data[6]];
          fixCoords(arr, -1);
          data[4] = arr[0];
          data[5] = arr[1];
          data[6] = arr[2];
          arr = [data[8], data[9], data[10]];
          fixCoords(arr, -1);
          data[8] = arr[0];
          data[9] = arr[1];
          data[10] = arr[2];
          arr = [data[3], data[7], data[11]];
          fixCoords(arr, -1);
          data[3] = arr[0];
          data[7] = arr[1];
          data[11] = arr[2];
        }
        return new THREE.Matrix4().set(data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15]);
      }
      function getConvertedIndex(index) {
        if (index > -1 && index < 3) {
          var members = ['X', 'Y', 'Z'],
              indices = {
                X: 0,
                Y: 1,
                Z: 2
              };
          index = getConvertedMember(members[index]);
          index = indices[index];
        }
        return index;
      }
      function getConvertedMember(member) {
        if (options.convertUpAxis) {
          switch (member) {
            case 'X':
              switch (upConversion) {
                case 'XtoY':
                case 'XtoZ':
                case 'YtoX':
                  member = 'Y';
                  break;
                case 'ZtoX':
                  member = 'Z';
                  break;
              }
              break;
            case 'Y':
              switch (upConversion) {
                case 'XtoY':
                case 'YtoX':
                case 'ZtoX':
                  member = 'X';
                  break;
                case 'XtoZ':
                case 'YtoZ':
                case 'ZtoY':
                  member = 'Z';
                  break;
              }
              break;
            case 'Z':
              switch (upConversion) {
                case 'XtoZ':
                  member = 'X';
                  break;
                case 'YtoZ':
                case 'ZtoX':
                case 'ZtoY':
                  member = 'Y';
                  break;
              }
              break;
          }
        }
        return member;
      }
      return {
        load: load,
        parse: parse,
        setPreferredShading: setPreferredShading,
        applySkin: applySkin,
        geometries: geometries,
        options: options
      };
    };
  })();
  return _retrieveGlobal();
});

$__System.registerDynamic("2a", ["25", "2d", "20", "8"], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  var THREE,
      P,
      findIndex,
      loadCollada,
      mergeObject,
      out$ = typeof exports != 'undefined' && exports || this;
  THREE = $__require('25');
  window.THREE = THREE;
  $__require('2d');
  P = $__require('20');
  findIndex = $__require('8').findIndex;
  out$.loadCollada = loadCollada = function(path) {
    return new P(function(resolve, reject) {
      var loader;
      loader = new THREE.ColladaLoader;
      loader.options.convertUpAxis = true;
      return loader.load(path, resolve);
    });
  };
  out$.mergeObject = mergeObject = function(root) {
    var submeshes,
        merged,
        getSubmesh,
        isTransparent,
        merge;
    submeshes = new Map;
    merged = new THREE.Object3D();
    getSubmesh = function(object) {
      var key,
          submesh;
      key = object.material;
      if (submeshes.has(key)) {
        return submeshes.get(key);
      }
      submesh = new THREE.Mesh(new THREE.Geometry, object.material.clone());
      submeshes.set(key, submesh);
      return submesh;
    };
    isTransparent = function(o) {
      var i$,
          ref$,
          len$,
          material;
      if (!o.material) {
        return false;
      }
      if (o.material.transparent) {
        return true;
      }
      if (!o.material.materials) {
        return false;
      }
      for (i$ = 0, len$ = (ref$ = o.material.materials).length; i$ < len$; ++i$) {
        material = ref$[i$];
        if (material.transparent) {
          return true;
        }
      }
      return false;
    };
    merge = function(object, matrix) {
      var clone,
          i$,
          ref$,
          len$,
          child,
          results$ = [];
      matrix == null && (matrix = new THREE.Matrix4);
      object.updateMatrix();
      if (isTransparent(object)) {
        clone = object.clone();
        clone.applyMatrix(matrix);
        merged.add(clone);
        return;
      }
      matrix = matrix.clone().multiply(object.matrix);
      if (object.geometry != null) {
        getSubmesh(object).geometry.merge(object.geometry, matrix);
      }
      for (i$ = 0, len$ = (ref$ = object.children).length; i$ < len$; ++i$) {
        child = ref$[i$];
        results$.push(merge(child, matrix));
      }
      return results$;
    };
    merge(root);
    submeshes.forEach(function(sub) {
      return merged.add(sub);
    });
    merged.applyMatrix(root.matrix);
    return merged;
  };
  return module.exports;
});

(function() {
var define = $__System.amdDefine;
(function() {
  'use strict';
  var PI = Math.PI,
      sin = Math.sin,
      cos = Math.cos,
      tan = Math.tan,
      asin = Math.asin,
      atan = Math.atan2,
      acos = Math.acos,
      rad = PI / 180;
  var dayMs = 1000 * 60 * 60 * 24,
      J1970 = 2440588,
      J2000 = 2451545;
  function toJulian(date) {
    return date.valueOf() / dayMs - 0.5 + J1970;
  }
  function fromJulian(j) {
    return new Date((j + 0.5 - J1970) * dayMs);
  }
  function toDays(date) {
    return toJulian(date) - J2000;
  }
  var e = rad * 23.4397;
  function rightAscension(l, b) {
    return atan(sin(l) * cos(e) - tan(b) * sin(e), cos(l));
  }
  function declination(l, b) {
    return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l));
  }
  function azimuth(H, phi, dec) {
    return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi));
  }
  function altitude(H, phi, dec) {
    return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H));
  }
  function siderealTime(d, lw) {
    return rad * (280.16 + 360.9856235 * d) - lw;
  }
  function solarMeanAnomaly(d) {
    return rad * (357.5291 + 0.98560028 * d);
  }
  function eclipticLongitude(M) {
    var C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)),
        P = rad * 102.9372;
    return M + C + P + PI;
  }
  function sunCoords(d) {
    var M = solarMeanAnomaly(d),
        L = eclipticLongitude(M);
    return {
      dec: declination(L, 0),
      ra: rightAscension(L, 0)
    };
  }
  var SunCalc = {};
  SunCalc.getPosition = function(date, lat, lng) {
    var lw = rad * -lng,
        phi = rad * lat,
        d = toDays(date),
        c = sunCoords(d),
        H = siderealTime(d, lw) - c.ra;
    return {
      azimuth: azimuth(H, phi, c.dec),
      altitude: altitude(H, phi, c.dec)
    };
  };
  var times = SunCalc.times = [[-0.833, 'sunrise', 'sunset'], [-0.3, 'sunriseEnd', 'sunsetStart'], [-6, 'dawn', 'dusk'], [-12, 'nauticalDawn', 'nauticalDusk'], [-18, 'nightEnd', 'night'], [6, 'goldenHourEnd', 'goldenHour']];
  SunCalc.addTime = function(angle, riseName, setName) {
    times.push([angle, riseName, setName]);
  };
  var J0 = 0.0009;
  function julianCycle(d, lw) {
    return Math.round(d - J0 - lw / (2 * PI));
  }
  function approxTransit(Ht, lw, n) {
    return J0 + (Ht + lw) / (2 * PI) + n;
  }
  function solarTransitJ(ds, M, L) {
    return J2000 + ds + 0.0053 * sin(M) - 0.0069 * sin(2 * L);
  }
  function hourAngle(h, phi, d) {
    return acos((sin(h) - sin(phi) * sin(d)) / (cos(phi) * cos(d)));
  }
  function getSetJ(h, lw, phi, dec, n, M, L) {
    var w = hourAngle(h, phi, dec),
        a = approxTransit(w, lw, n);
    return solarTransitJ(a, M, L);
  }
  SunCalc.getTimes = function(date, lat, lng) {
    var lw = rad * -lng,
        phi = rad * lat,
        d = toDays(date),
        n = julianCycle(d, lw),
        ds = approxTransit(0, lw, n),
        M = solarMeanAnomaly(ds),
        L = eclipticLongitude(M),
        dec = declination(L, 0),
        Jnoon = solarTransitJ(ds, M, L),
        i,
        len,
        time,
        Jset,
        Jrise;
    var result = {
      solarNoon: fromJulian(Jnoon),
      nadir: fromJulian(Jnoon - 0.5)
    };
    for (i = 0, len = times.length; i < len; i += 1) {
      time = times[i];
      Jset = getSetJ(time[0] * rad, lw, phi, dec, n, M, L);
      Jrise = Jnoon - (Jset - Jnoon);
      result[time[1]] = fromJulian(Jrise);
      result[time[2]] = fromJulian(Jset);
    }
    return result;
  };
  function moonCoords(d) {
    var L = rad * (218.316 + 13.176396 * d),
        M = rad * (134.963 + 13.064993 * d),
        F = rad * (93.272 + 13.229350 * d),
        l = L + rad * 6.289 * sin(M),
        b = rad * 5.128 * sin(F),
        dt = 385001 - 20905 * cos(M);
    return {
      ra: rightAscension(l, b),
      dec: declination(l, b),
      dist: dt
    };
  }
  SunCalc.getMoonPosition = function(date, lat, lng) {
    var lw = rad * -lng,
        phi = rad * lat,
        d = toDays(date),
        c = moonCoords(d),
        H = siderealTime(d, lw) - c.ra,
        h = altitude(H, phi, c.dec);
    h = h + rad * 0.017 / tan(h + rad * 10.26 / (h + rad * 5.10));
    return {
      azimuth: azimuth(H, phi, c.dec),
      altitude: h,
      distance: c.dist
    };
  };
  SunCalc.getMoonIllumination = function(date) {
    var d = toDays(date),
        s = sunCoords(d),
        m = moonCoords(d),
        sdist = 149598000,
        phi = acos(sin(s.dec) * sin(m.dec) + cos(s.dec) * cos(m.dec) * cos(s.ra - m.ra)),
        inc = atan(sdist * sin(phi), m.dist - sdist * cos(phi)),
        angle = atan(cos(s.dec) * sin(s.ra - m.ra), sin(s.dec) * cos(m.dec) - cos(s.dec) * sin(m.dec) * cos(s.ra - m.ra));
    return {
      fraction: (1 + cos(inc)) / 2,
      phase: 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI,
      angle: angle
    };
  };
  function hoursLater(date, h) {
    return new Date(date.valueOf() + h * dayMs / 24);
  }
  SunCalc.getMoonTimes = function(date, lat, lng) {
    var t = new Date(date);
    t.setHours(0);
    t.setMinutes(0);
    t.setSeconds(0);
    t.setMilliseconds(0);
    var hc = 0.133 * rad,
        h0 = SunCalc.getMoonPosition(t, lat, lng).altitude - hc,
        h1,
        h2,
        rise,
        set,
        a,
        b,
        xe,
        ye,
        d,
        roots,
        x1,
        x2,
        dx;
    for (var i = 1; i <= 24; i += 2) {
      h1 = SunCalc.getMoonPosition(hoursLater(t, i), lat, lng).altitude - hc;
      h2 = SunCalc.getMoonPosition(hoursLater(t, i + 1), lat, lng).altitude - hc;
      a = (h0 + h2) / 2 - h1;
      b = (h2 - h0) / 2;
      xe = -b / (2 * a);
      ye = (a * xe + b) * xe + h1;
      d = b * b - 4 * a * h1;
      roots = 0;
      if (d >= 0) {
        dx = Math.sqrt(d) / (Math.abs(a) * 2);
        x1 = xe - dx;
        x2 = xe + dx;
        if (Math.abs(x1) <= 1)
          roots++;
        if (Math.abs(x2) <= 1)
          roots++;
        if (x1 < -1)
          x1 = x2;
      }
      if (roots === 1) {
        if (h0 < 0)
          rise = i + x1;
        else
          set = i + x1;
      } else if (roots === 2) {
        rise = i + (ye < 0 ? x2 : x1);
        set = i + (ye < 0 ? x1 : x2);
      }
      if (rise && set)
        break;
      h0 = h2;
    }
    var result = {};
    if (rise)
      result.rise = hoursLater(t, rise);
    if (set)
      result.set = hoursLater(t, set);
    if (!rise && !set)
      result[ye > 0 ? 'alwaysUp' : 'alwaysDown'] = true;
    return result;
  };
  if (typeof define === 'function' && define.amd)
    define("30", [], SunCalc);
  else if (typeof module !== 'undefined')
    module.exports = SunCalc;
  else
    window.SunCalc = SunCalc;
}());

})();
$__System.registerDynamic("31", ["25", "26", "19", "20", "1a", "2f", "2a", "30"], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  var THREE,
      Cannon,
      $,
      P,
      seqr,
      ref$,
      loadCollada,
      mergeObject,
      svgToCanvas,
      svgToSign,
      SineGratingBitmap,
      SineGrating,
      ArrowMarker,
      TrackingMarker,
      SpeedSign,
      FinishSign,
      StopSign,
      BallBoard,
      TrafficLight,
      SunCalc,
      addSky,
      SceneDisplay,
      addMarkerScreen,
      out$ = typeof exports != 'undefined' && exports || this,
      slice$ = [].slice;
  THREE = $__require('25');
  Cannon = $__require('26');
  $ = $__require('19');
  P = $__require('20');
  seqr = $__require('1a');
  $__require('2f');
  ref$ = $__require('2a'), loadCollada = ref$.loadCollada, mergeObject = ref$.mergeObject;
  svgToCanvas = seqr.bind(function*(el, width, height, pw, ph) {
    var img,
        data,
        p,
        DOMURL,
        ref$,
        canvas,
        ctx;
    pw == null && (pw = 0);
    ph == null && (ph = 0);
    img = new Image;
    data = new Blob([el.outerHTML], {type: 'image/svg+xml;charset=utf-8'});
    p = new P(function(accept, reject) {
      img.onload = accept;
      return img.onerror = reject;
    });
    DOMURL = (ref$ = window.URL) != null ? ref$ : (ref$ = window.webkitURL) != null ? ref$ : window;
    img.src = DOMURL.createObjectURL(data);
    (yield p);
    canvas = document.createElement('canvas');
    canvas.width = width + pw;
    canvas.height = height + ph;
    ctx = canvas.getContext('2d');
    ctx.drawImage(img, 0, 0, width, height);
    DOMURL.revokeObjectURL(img.src);
    return canvas;
  });
  svgToSign = seqr.bind(function*(img, arg$) {
    var pixelsPerMeter,
        ref$,
        texSize,
        meters,
        faceWidth,
        faceHeight,
        w,
        pw,
        h,
        ph,
        raster,
        texture,
        face;
    pixelsPerMeter = (ref$ = (arg$ != null ? arg$ : {}).pixelsPerMeter) != null ? ref$ : 100;
    texSize = function(v) {
      var i$,
          to$,
          i,
          pow2;
      v = Math.round(v * pixelsPerMeter);
      if (v < 1) {
        return 0;
      }
      for (i$ = 0, to$ = Infinity; i$ <= to$; ++i$) {
        i = i$;
        pow2 = Math.pow(2, i);
        if (pow2 > v) {
          break;
        }
      }
      return [pow2, v - pow2];
    };
    meters = function(v) {
      v = v.baseVal;
      v.convertToSpecifiedUnits(v.SVG_LENGTHTYPE_CM);
      return v.valueInSpecifiedUnits / 100;
    };
    faceWidth = meters(img.prop('width'));
    faceHeight = meters(img.prop('height'));
    ref$ = texSize(faceWidth), w = ref$[0], pw = ref$[1];
    ref$ = texSize(faceHeight), h = ref$[0], ph = ref$[1];
    raster = (yield svgToCanvas(img[0], w, h, 0, 0));
    texture = new THREE.Texture(raster);
    texture.needsUpdate = true;
    face = new THREE.Mesh(new THREE.PlaneGeometry(faceWidth, faceHeight), new THREE.MeshLambertMaterial({
      map: texture,
      side: THREE.DoubleSide,
      transparent: true
    }));
    face.width = faceWidth;
    face.height = faceHeight;
    return face;
  });
  out$.SineGratingBitmap = SineGratingBitmap = function(arg$) {
    var ref$,
        resolution,
        ref1$,
        cycles,
        canvas,
        ctx,
        img,
        setPixel,
        i$,
        x,
        j$,
        y,
        rx,
        ry,
        d,
        v;
    ref$ = arg$ != null ? arg$ : {}, resolution = (ref1$ = ref$.resolution) != null ? ref1$ : 1024, cycles = (ref1$ = ref$.cycles) != null ? ref1$ : 8;
    canvas = document.createElement('canvas');
    canvas.width = resolution;
    canvas.height = resolution;
    ctx = canvas.getContext('2d');
    img = ctx.createImageData(resolution, resolution);
    setPixel = function(x, y, value) {
      var i,
          c;
      i = (y * resolution + x) * 4;
      c = value * 255;
      img.data[i] = 255;
      img.data[i + 1] = 255;
      img.data[i + 2] = 255;
      return img.data[i + 3] = c;
    };
    for (i$ = 0; i$ < resolution; ++i$) {
      x = i$;
      for (j$ = 0; j$ < resolution; ++j$) {
        y = j$;
        rx = x / (resolution / 2) - 1;
        ry = y / (resolution / 2) - 1;
        d = Math.sqrt(Math.pow(rx, 2) + Math.pow(ry, 2));
        v = (Math.cos(rx * cycles * Math.PI) + 1) / 2;
        v *= Math.cos(d * Math.PI / 2);
        v *= d < 1.0;
        setPixel(x, y, v);
      }
    }
    ctx.putImageData(img, 0, 0);
    return canvas;
  };
  SineGrating = function(opts) {
    var canvas,
        texture,
        face;
    opts == null && (opts = {});
    canvas = SineGratingBitmap(opts);
    texture = new THREE.Texture(canvas);
    texture.needsUpdate = true;
    face = new THREE.Mesh(new THREE.PlaneGeometry(1, 1), new THREE.MeshLambertMaterial({
      map: texture,
      side: THREE.DoubleSide,
      transparent: true
    }));
    return face;
  };
  out$.ArrowMarker = ArrowMarker = seqr.bind(function*(opts) {
    var marker,
        signs,
        load,
        target;
    opts == null && (opts = {});
    marker = new THREE.Object3D;
    marker.signs = signs = {};
    load = seqr.bind(function*(name, file) {
      var doc,
          img,
          obj;
      doc = $((yield $.ajax(file, {dataType: 'xml'})));
      img = $(doc.find("svg"));
      obj = (yield svgToSign(img));
      obj.visible = false;
      marker.add(obj);
      return signs[name] = obj;
    });
    marker.setSign = function(name) {
      var n,
          ref$,
          o;
      for (n in ref$ = signs) {
        o = ref$[n];
        o.visible = false;
      }
      if (!(name in signs)) {
        return;
      }
      return signs[name].visible = true;
    };
    target = SineGrating(opts);
    target.visible = false;
    target.transparent = true;
    signs.target = target;
    marker.add(target);
    marker.setFrequency = function(frequency) {
      if (frequency === target._frequency) {
        return;
      }
      target.material.map = new THREE.Texture(SineGratingBitmap({cycles: frequency}));
      target.material.map.needsUpdate = true;
      target.material.needsUpdate = true;
      return target._frequency = frequency;
    };
    (yield load('cue', './res/signs/arrow-circle.svg'));
    (yield load('mask', './res/signs/arrow-mask.svg'));
    (yield load('wait', './res/signs/arrow-wait.svg'));
    (yield load('query', './res/signs/arrow-query.svg'));
    (yield load('success', './res/signs/arrow-success.svg'));
    (yield load('failure', './res/signs/arrow-failure.svg'));
    return marker;
  });
  out$.TrackingMarker = TrackingMarker = seqr.bind(function*() {
    var doc,
        img,
        target,
        crosshair,
        marker;
    doc = $((yield $.ajax("./res/signs/trackerbr.svg", {dataType: 'xml'})));
    img = $(doc.find("svg"));
    target = (yield svgToSign(img, {pixelsPerMeter: 2000}));
    target.position.z = -2;
    doc = $((yield $.ajax("./res/signs/trackerbar.svg", {dataType: 'xml'})));
    img = $(doc.find("svg"));
    crosshair = (yield svgToSign(img, {pixelsPerMeter: 2000}));
    marker = new THREE.Object3D;
    marker.add(crosshair);
    marker.add(target);
    marker.crosshair = crosshair;
    marker.target = target;
    return marker;
  });
  out$.SpeedSign = SpeedSign = seqr.bind(function*(limit, arg$) {
    var opts,
        ref$,
        height,
        ref1$,
        poleRadius,
        doc,
        img,
        sign,
        face,
        pole;
    ref$ = arg$ != null ? arg$ : opts = {}, height = (ref1$ = ref$.height) != null ? ref1$ : 2, poleRadius = (ref1$ = ref$.poleRadius) != null ? ref1$ : 0.07 / 2;
    doc = $((yield $.ajax("./res/signs/speedsign.svg", {dataType: 'xml'})));
    img = $(doc.find("svg"));
    img.find('#limit')[0].textContent = limit;
    sign = new THREE.Object3D;
    face = (yield svgToSign(img, opts));
    face.position.y = height;
    face.position.z = -poleRadius - 0.01;
    face.rotation.y = Math.PI;
    sign.add(face);
    pole = new THREE.Mesh(new THREE.CylinderGeometry(poleRadius, poleRadius, height, 32), new THREE.MeshLambertMaterial({color: 0xdddddd}));
    pole.position.y = height / 2;
    sign.add(pole);
    sign.traverse(function(o) {
      o.castShadow = true;
      return o.receiveShadow = false;
    });
    return sign;
  });
  out$.FinishSign = FinishSign = seqr.bind(function*(arg$) {
    var opts,
        ref$,
        height,
        ref1$,
        texSize,
        poleRadius,
        doc,
        img,
        face,
        sign,
        pole,
        watcherWidth,
        watcherHeight,
        halfExtent,
        watcherShape,
        x$,
        watcher,
        self;
    ref$ = arg$ != null ? arg$ : opts = {}, height = (ref1$ = ref$.height) != null ? ref1$ : 4, texSize = (ref1$ = ref$.texSize) != null ? ref1$ : [256, 256], poleRadius = (ref1$ = ref$.poleRadius) != null ? ref1$ : 0.07 / 2;
    doc = $((yield $.ajax("./res/signs/finish.svg", {dataType: 'xml'})));
    img = $(doc.find("svg"));
    face = (yield svgToSign(img, opts));
    sign = new THREE.Object3D;
    face.position.y = height;
    face.position.z = -poleRadius - 0.01;
    face.rotation.y = Math.PI;
    sign.add(face);
    pole = new THREE.Mesh(new THREE.CylinderGeometry(poleRadius, poleRadius, height, 32), new THREE.MeshLambertMaterial({color: 0xdddddd}));
    pole.position.y = height / 2;
    pole.position.x = face.width / 2;
    sign.add(pole);
    pole = pole.clone();
    pole.position.x = -face.width / 2;
    sign.add(pole);
    sign.traverse(function(o) {
      o.castShadow = true;
      return o.receiveShadow = false;
    });
    watcherWidth = face.width;
    watcherHeight = height;
    halfExtent = new Cannon.Vec3(watcherWidth / 2, watcherHeight / 2, 0.1);
    watcherShape = new Cannon.Box(halfExtent);
    x$ = watcher = new Cannon.Body({
      mass: 0,
      type: Cannon.Body.STATIC
    });
    x$.addShape(watcherShape, new Cannon.Vec3(0, watcherHeight / 2, 0));
    x$.objectClass = "finish-line";
    x$.collisionResponse = false;
    x$.preventCollisionEvent = function() {
      return true;
    };
    self = {
      onPassed: Signal(),
      bodyPassed: function(body) {
        return new Promise(function(accept) {
          return watcher.addEventListener("collide", function(e) {
            if (e.body === body) {
              accept(e);
              return false;
            }
          });
        });
      },
      visual: sign,
      position: watcher.position,
      addTo: function(scene) {
        scene.visual.add(sign);
        scene.physics.add(watcher);
        return scene.bindPhys(watcher, sign);
      }
    };
    watcher.addEventListener("collide", function(e) {
      return self.onPassed.dispatch(e);
    });
    return self;
  });
  out$.StopSign = StopSign = seqr.bind(function*(arg$) {
    var opts,
        ref$,
        height,
        ref1$,
        poleRadius,
        doc,
        img,
        sign,
        face,
        pole,
        watcherWidth,
        watcherHeight,
        halfExtent,
        watcherShape,
        x$,
        watcher,
        self;
    ref$ = arg$ != null ? arg$ : opts = {}, height = (ref1$ = ref$.height) != null ? ref1$ : 2, poleRadius = (ref1$ = ref$.poleRadius) != null ? ref1$ : 0.07 / 2;
    doc = $((yield $.ajax("./res/signs/stopsign.svg", {dataType: 'xml'})));
    img = $(doc.find("svg"));
    sign = new THREE.Object3D;
    face = (yield svgToSign(img, opts));
    face.position.y = height;
    face.position.z = -poleRadius - 0.01;
    face.rotation.y = Math.PI;
    sign.add(face);
    pole = new THREE.Mesh(new THREE.CylinderGeometry(poleRadius, poleRadius, height, 32), new THREE.MeshLambertMaterial({color: 0xdddddd}));
    pole.position.y = height / 2;
    sign.add(pole);
    watcherWidth = 5;
    watcherHeight = 10;
    halfExtent = new Cannon.Vec3(watcherWidth / 2, watcherHeight / 2, 0.1);
    watcherShape = new Cannon.Box(halfExtent);
    x$ = watcher = new Cannon.Body({
      mass: 0,
      type: Cannon.Body.STATIC
    });
    x$.addShape(watcherShape, halfExtent);
    x$.objectClass = "stop-sign";
    x$.collisionResponse = false;
    self = {
      visual: sign,
      position: watcher.position,
      addTo: function(scene) {
        scene.visual.add(sign);
        scene.physics.add(watcher);
        return scene.bindPhys(watcher, sign);
      }
    };
    return self;
  });
  out$.BallBoard = BallBoard = seqr.bind(function*() {
    var doc,
        img,
        ball,
        board,
        midpoint,
        obj,
        turnable;
    doc = $((yield $.ajax("./res/items/circle.svg", {dataType: 'xml'})));
    img = $(doc.find("svg"));
    ball = (yield svgToSign(img));
    ball.scale.set(0.05, 0.05, 0.05);
    ball.position.y = 0.05 / 2;
    doc = $((yield $.ajax("./res/items/level.svg", {dataType: 'xml'})));
    img = $(doc.find("svg"));
    board = (yield svgToSign(img, {pixelsPerMeter: 1000}));
    doc = $((yield $.ajax("./res/items/balancepoint.svg", {dataType: 'xml'})));
    img = $(doc.find("svg"));
    midpoint = (yield svgToSign(img, {pixelsPerMeter: 1000}));
    obj = new THREE.Object3D;
    obj.add(midpoint);
    turnable = new THREE.Object3D;
    turnable.add(ball);
    obj.ball = ball;
    turnable.add(board);
    obj.turnable = turnable;
    obj.add(turnable);
    return obj;
  });
  out$.TrafficLight = TrafficLight = seqr.bind(function*() {
    var data,
        mod,
        x$,
        model,
        lights,
        watcherWidth,
        watcherHeight,
        halfExtent,
        watcherShape,
        y$,
        watcher,
        i$,
        onGreen;
    data = (yield loadCollada('res/signs/TrafficLight.dae'));
    mod = data.scene.children[0];
    mod.scale.set(0.03, 0.03, 0.03);
    mod.rotation.y = Math.PI;
    mod.position.y -= 1.0;
    x$ = model = new THREE.Object3D;
    x$.add(mod);
    lights = {
      red: model.getObjectByName('Red'),
      yellow: model.getObjectByName('Yellow'),
      green: model.getObjectByName('Green')
    };
    watcherWidth = 5;
    watcherHeight = 10;
    halfExtent = new Cannon.Vec3(5 / 2, 10 / 2, 0.1);
    watcherShape = new Cannon.Box(halfExtent);
    y$ = watcher = new Cannon.Body({
      mass: 0,
      type: Cannon.Body.STATIC
    });
    y$.addShape(watcherShape, halfExtent);
    y$.objectClass = "traffic-light";
    y$.collisionResponse = false;
    for (i$ in lights) {
      (fn$.call(this, i$, lights[i$]));
    }
    onGreen = Signal();
    lights.red.on();
    return {
      getState: function() {
        return {
          red: lights.red.isOn,
          yellow: lights.yellow.isOn,
          green: lights.green.isOn
        };
      },
      switchToGreen: seqr.bind(function*() {
        if (lights.green.isOn) {
          lights.red.off();
          lights.yellow.off();
          return;
        }
        lights.red.on();
        lights.yellow.on();
        (yield P.delay(1 * 1000));
        lights.red.off();
        lights.yellow.off();
        lights.green.on();
        return onGreen.dispatch();
      }),
      visual: model,
      position: watcher.position,
      addTo: function(scene) {
        scene.visual.add(model);
        scene.physics.add(watcher);
        scene.bindPhys(watcher, model);
        return onGreen(function() {
          return scene.physics.removeBody(watcher);
        });
      }
    };
    function fn$(name, light) {
      var materials,
          res$,
          i$,
          len$,
          material,
          hsl;
      materials = light.children[0].material.materials;
      res$ = [];
      for (i$ = 0, len$ = materials.length; i$ < len$; ++i$) {
        material = materials[i$];
        material = material.clone();
        hsl = material.color.getHSL();
        material.color.setHSL(hsl.h, hsl.s, 0.1);
        res$.push(material);
      }
      materials = res$;
      light.children[0].material.materials = materials;
      light.on = function() {
        var i$,
            ref$,
            len$,
            material,
            hsl;
        for (i$ = 0, len$ = (ref$ = materials).length; i$ < len$; ++i$) {
          material = ref$[i$];
          hsl = material.color.getHSL();
          material.emissive.setHSL(hsl.h, 0.9, 0.5);
        }
        return light.isOn = true;
      };
      light.off = function() {
        var i$,
            ref$,
            len$,
            material,
            hsl;
        for (i$ = 0, len$ = (ref$ = materials).length; i$ < len$; ++i$) {
          material = ref$[i$];
          hsl = material.color.getHSL();
          material.emissive.setHSL(hsl.h, 0.0, 0.0);
        }
        return light.isOn = false;
      };
    }
  });
  SunCalc = $__require('30');
  out$.addSky = addSky = function(scene, arg$) {
    var ref$,
        location,
        ref1$,
        date,
        distance,
        dome,
        sky,
        x$,
        sunlight,
        position,
        updatePosition;
    ref$ = arg$ != null ? arg$ : {}, location = (ref1$ = ref$.location) != null ? ref1$ : [60, 0], date = ref$.date;
    if (date == null) {
      date = new Date(1970, 5, 24, 12);
    }
    distance = 4500;
    dome = new THREE.Object3D;
    scene.visual.add(dome);
    sky = new THREE.Sky;
    dome.add(sky.mesh);
    x$ = sunlight = new THREE.DirectionalLight(0xffffff, 0.5);
    x$.castShadow = true;
    x$.shadowCameraNear = distance / 2;
    x$.shadowCameraFar = distance * 2;
    x$.shadowCameraLeft = -distance;
    x$.shadowCameraRight = distance;
    x$.shadowCameraTop = distance;
    x$.shadowCameraBottom = -distance;
    x$.shadowMapWidth = 2048;
    x$.shadowMapHeight = 2048;
    x$.shadowBias = 0.0001;
    x$.shadowDarkness = 1.0;
    x$.target = dome;
    dome.add(sunlight);
    scene.visual.add(new THREE.AmbientLight(0xa0a0a0));
    position = new THREE.Vector3;
    scene.beforeRender.add(function() {
      position.setFromMatrixPosition(scene.camera.matrixWorld);
      dome.position.z = position.z;
      return dome.position.x = position.x;
    });
    updatePosition = function() {
      var degs,
          position;
      degs = SunCalc.getPosition.apply(SunCalc, [date].concat(slice$.call(location)));
      position = new THREE.Vector3(0, 0, distance);
      position.applyEuler(new THREE.Euler(-degs.altitude, degs.azimuth, 0, "YXZ"));
      sky.uniforms.sunPosition.value.copy(position);
      return sunlight.position.copy(position);
    };
    updatePosition();
    return {
      setDate: function(newDate) {
        date = new Date(newDate.getTime());
        return updatePosition();
      },
      getDate: function() {
        return new Date(date.getTime());
      }
    };
  };
  out$.SceneDisplay = SceneDisplay = seqr.bind(function*(arg$) {
    var ref$,
        width,
        ref1$,
        height,
        rtTexture,
        geo,
        mat,
        object;
    ref$ = arg$ != null ? arg$ : {}, width = (ref1$ = ref$.width) != null ? ref1$ : 1024, height = (ref1$ = ref$.height) != null ? ref1$ : 1024;
    rtTexture = new THREE.WebGLRenderTarget(width, height, {
      minFilter: THREE.LinearFilter,
      magFilter: THREE.NearestFilter,
      format: THREE.RGBFormat
    });
    geo = new THREE.PlaneGeometry(1, 1);
    mat = new THREE.MeshBasicMaterial({
      color: 0xffffff,
      map: rtTexture
    });
    object = new THREE.Mesh(geo, mat);
    return {
      object: object,
      renderTarget: rtTexture
    };
  });
  out$.addMarkerScreen = addMarkerScreen = function(scene) {
    var aspect,
        t,
        b,
        l,
        r,
        s,
        pos,
        i$,
        i,
        path,
        texture,
        marker,
        results$ = [];
    aspect = screen.width / screen.height;
    t = scene.camera.top;
    b = scene.camera.bottom;
    l = -aspect;
    r = aspect;
    s = 0.2;
    pos = [[l + s, t - s], [r - s, t - s], [l + s, -t + s], [r - s, -t + s]];
    for (i$ = 0; i$ < 4; ++i$) {
      i = i$;
      path = 'res/markers/' + i + '_marker.png';
      texture = THREE.ImageUtils.loadTexture(path);
      marker = new THREE.Mesh(new THREE.PlaneGeometry(s, s), new THREE.MeshBasicMaterial({map: texture}));
      marker.position.x = pos[i][0];
      marker.position.y = pos[i][1];
      results$.push(scene.visual.add(marker));
    }
    return results$;
  };
  return module.exports;
});

(function() {
var define = $__System.amdDefine;
;
(function() {
  var undefined;
  var VERSION = '3.10.1';
  var BIND_FLAG = 1,
      BIND_KEY_FLAG = 2,
      CURRY_BOUND_FLAG = 4,
      CURRY_FLAG = 8,
      CURRY_RIGHT_FLAG = 16,
      PARTIAL_FLAG = 32,
      PARTIAL_RIGHT_FLAG = 64,
      ARY_FLAG = 128,
      REARG_FLAG = 256;
  var DEFAULT_TRUNC_LENGTH = 30,
      DEFAULT_TRUNC_OMISSION = '...';
  var HOT_COUNT = 150,
      HOT_SPAN = 16;
  var LARGE_ARRAY_SIZE = 200;
  var LAZY_FILTER_FLAG = 1,
      LAZY_MAP_FLAG = 2;
  var FUNC_ERROR_TEXT = 'Expected a function';
  var PLACEHOLDER = '__lodash_placeholder__';
  var argsTag = '[object Arguments]',
      arrayTag = '[object Array]',
      boolTag = '[object Boolean]',
      dateTag = '[object Date]',
      errorTag = '[object Error]',
      funcTag = '[object Function]',
      mapTag = '[object Map]',
      numberTag = '[object Number]',
      objectTag = '[object Object]',
      regexpTag = '[object RegExp]',
      setTag = '[object Set]',
      stringTag = '[object String]',
      weakMapTag = '[object WeakMap]';
  var arrayBufferTag = '[object ArrayBuffer]',
      float32Tag = '[object Float32Array]',
      float64Tag = '[object Float64Array]',
      int8Tag = '[object Int8Array]',
      int16Tag = '[object Int16Array]',
      int32Tag = '[object Int32Array]',
      uint8Tag = '[object Uint8Array]',
      uint8ClampedTag = '[object Uint8ClampedArray]',
      uint16Tag = '[object Uint16Array]',
      uint32Tag = '[object Uint32Array]';
  var reEmptyStringLeading = /\b__p \+= '';/g,
      reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
      reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
  var reEscapedHtml = /&(?:amp|lt|gt|quot|#39|#96);/g,
      reUnescapedHtml = /[&<>"'`]/g,
      reHasEscapedHtml = RegExp(reEscapedHtml.source),
      reHasUnescapedHtml = RegExp(reUnescapedHtml.source);
  var reEscape = /<%-([\s\S]+?)%>/g,
      reEvaluate = /<%([\s\S]+?)%>/g,
      reInterpolate = /<%=([\s\S]+?)%>/g;
  var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\n\\]|\\.)*?\1)\]/,
      reIsPlainProp = /^\w*$/,
      rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\n\\]|\\.)*?)\2)\]/g;
  var reRegExpChars = /^[:!,]|[\\^$.*+?()[\]{}|\/]|(^[0-9a-fA-Fnrtuvx])|([\n\r\u2028\u2029])/g,
      reHasRegExpChars = RegExp(reRegExpChars.source);
  var reComboMark = /[\u0300-\u036f\ufe20-\ufe23]/g;
  var reEscapeChar = /\\(\\)?/g;
  var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
  var reFlags = /\w*$/;
  var reHasHexPrefix = /^0[xX]/;
  var reIsHostCtor = /^\[object .+?Constructor\]$/;
  var reIsUint = /^\d+$/;
  var reLatin1 = /[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g;
  var reNoMatch = /($^)/;
  var reUnescapedString = /['\n\r\u2028\u2029\\]/g;
  var reWords = (function() {
    var upper = '[A-Z\\xc0-\\xd6\\xd8-\\xde]',
        lower = '[a-z\\xdf-\\xf6\\xf8-\\xff]+';
    return RegExp(upper + '+(?=' + upper + lower + ')|' + upper + '?' + lower + '|' + upper + '+|[0-9]+', 'g');
  }());
  var contextProps = ['Array', 'ArrayBuffer', 'Date', 'Error', 'Float32Array', 'Float64Array', 'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Math', 'Number', 'Object', 'RegExp', 'Set', 'String', '_', 'clearTimeout', 'isFinite', 'parseFloat', 'parseInt', 'setTimeout', 'TypeError', 'Uint8Array', 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap'];
  var templateCounter = -1;
  var typedArrayTags = {};
  typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = typedArrayTags[uint32Tag] = true;
  typedArrayTags[argsTag] = typedArrayTags[arrayTag] = typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = typedArrayTags[dateTag] = typedArrayTags[errorTag] = typedArrayTags[funcTag] = typedArrayTags[mapTag] = typedArrayTags[numberTag] = typedArrayTags[objectTag] = typedArrayTags[regexpTag] = typedArrayTags[setTag] = typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false;
  var cloneableTags = {};
  cloneableTags[argsTag] = cloneableTags[arrayTag] = cloneableTags[arrayBufferTag] = cloneableTags[boolTag] = cloneableTags[dateTag] = cloneableTags[float32Tag] = cloneableTags[float64Tag] = cloneableTags[int8Tag] = cloneableTags[int16Tag] = cloneableTags[int32Tag] = cloneableTags[numberTag] = cloneableTags[objectTag] = cloneableTags[regexpTag] = cloneableTags[stringTag] = cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;
  cloneableTags[errorTag] = cloneableTags[funcTag] = cloneableTags[mapTag] = cloneableTags[setTag] = cloneableTags[weakMapTag] = false;
  var deburredLetters = {
    '\xc0': 'A',
    '\xc1': 'A',
    '\xc2': 'A',
    '\xc3': 'A',
    '\xc4': 'A',
    '\xc5': 'A',
    '\xe0': 'a',
    '\xe1': 'a',
    '\xe2': 'a',
    '\xe3': 'a',
    '\xe4': 'a',
    '\xe5': 'a',
    '\xc7': 'C',
    '\xe7': 'c',
    '\xd0': 'D',
    '\xf0': 'd',
    '\xc8': 'E',
    '\xc9': 'E',
    '\xca': 'E',
    '\xcb': 'E',
    '\xe8': 'e',
    '\xe9': 'e',
    '\xea': 'e',
    '\xeb': 'e',
    '\xcC': 'I',
    '\xcd': 'I',
    '\xce': 'I',
    '\xcf': 'I',
    '\xeC': 'i',
    '\xed': 'i',
    '\xee': 'i',
    '\xef': 'i',
    '\xd1': 'N',
    '\xf1': 'n',
    '\xd2': 'O',
    '\xd3': 'O',
    '\xd4': 'O',
    '\xd5': 'O',
    '\xd6': 'O',
    '\xd8': 'O',
    '\xf2': 'o',
    '\xf3': 'o',
    '\xf4': 'o',
    '\xf5': 'o',
    '\xf6': 'o',
    '\xf8': 'o',
    '\xd9': 'U',
    '\xda': 'U',
    '\xdb': 'U',
    '\xdc': 'U',
    '\xf9': 'u',
    '\xfa': 'u',
    '\xfb': 'u',
    '\xfc': 'u',
    '\xdd': 'Y',
    '\xfd': 'y',
    '\xff': 'y',
    '\xc6': 'Ae',
    '\xe6': 'ae',
    '\xde': 'Th',
    '\xfe': 'th',
    '\xdf': 'ss'
  };
  var htmlEscapes = {
    '&': '&amp;',
    '<': '&lt;',
    '>': '&gt;',
    '"': '&quot;',
    "'": '&#39;',
    '`': '&#96;'
  };
  var htmlUnescapes = {
    '&amp;': '&',
    '&lt;': '<',
    '&gt;': '>',
    '&quot;': '"',
    '&#39;': "'",
    '&#96;': '`'
  };
  var objectTypes = {
    'function': true,
    'object': true
  };
  var regexpEscapes = {
    '0': 'x30',
    '1': 'x31',
    '2': 'x32',
    '3': 'x33',
    '4': 'x34',
    '5': 'x35',
    '6': 'x36',
    '7': 'x37',
    '8': 'x38',
    '9': 'x39',
    'A': 'x41',
    'B': 'x42',
    'C': 'x43',
    'D': 'x44',
    'E': 'x45',
    'F': 'x46',
    'a': 'x61',
    'b': 'x62',
    'c': 'x63',
    'd': 'x64',
    'e': 'x65',
    'f': 'x66',
    'n': 'x6e',
    'r': 'x72',
    't': 'x74',
    'u': 'x75',
    'v': 'x76',
    'x': 'x78'
  };
  var stringEscapes = {
    '\\': '\\',
    "'": "'",
    '\n': 'n',
    '\r': 'r',
    '\u2028': 'u2028',
    '\u2029': 'u2029'
  };
  var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports;
  var freeModule = objectTypes[typeof module] && module && !module.nodeType && module;
  var freeGlobal = freeExports && freeModule && typeof global == 'object' && global && global.Object && global;
  var freeSelf = objectTypes[typeof self] && self && self.Object && self;
  var freeWindow = objectTypes[typeof window] && window && window.Object && window;
  var moduleExports = freeModule && freeModule.exports === freeExports && freeExports;
  var root = freeGlobal || ((freeWindow !== (this && this.window)) && freeWindow) || freeSelf || this;
  function baseCompareAscending(value, other) {
    if (value !== other) {
      var valIsNull = value === null,
          valIsUndef = value === undefined,
          valIsReflexive = value === value;
      var othIsNull = other === null,
          othIsUndef = other === undefined,
          othIsReflexive = other === other;
      if ((value > other && !othIsNull) || !valIsReflexive || (valIsNull && !othIsUndef && othIsReflexive) || (valIsUndef && othIsReflexive)) {
        return 1;
      }
      if ((value < other && !valIsNull) || !othIsReflexive || (othIsNull && !valIsUndef && valIsReflexive) || (othIsUndef && valIsReflexive)) {
        return -1;
      }
    }
    return 0;
  }
  function baseFindIndex(array, predicate, fromRight) {
    var length = array.length,
        index = fromRight ? length : -1;
    while ((fromRight ? index-- : ++index < length)) {
      if (predicate(array[index], index, array)) {
        return index;
      }
    }
    return -1;
  }
  function baseIndexOf(array, value, fromIndex) {
    if (value !== value) {
      return indexOfNaN(array, fromIndex);
    }
    var index = fromIndex - 1,
        length = array.length;
    while (++index < length) {
      if (array[index] === value) {
        return index;
      }
    }
    return -1;
  }
  function baseIsFunction(value) {
    return typeof value == 'function' || false;
  }
  function baseToString(value) {
    return value == null ? '' : (value + '');
  }
  function charsLeftIndex(string, chars) {
    var index = -1,
        length = string.length;
    while (++index < length && chars.indexOf(string.charAt(index)) > -1) {}
    return index;
  }
  function charsRightIndex(string, chars) {
    var index = string.length;
    while (index-- && chars.indexOf(string.charAt(index)) > -1) {}
    return index;
  }
  function compareAscending(object, other) {
    return baseCompareAscending(object.criteria, other.criteria) || (object.index - other.index);
  }
  function compareMultiple(object, other, orders) {
    var index = -1,
        objCriteria = object.criteria,
        othCriteria = other.criteria,
        length = objCriteria.length,
        ordersLength = orders.length;
    while (++index < length) {
      var result = baseCompareAscending(objCriteria[index], othCriteria[index]);
      if (result) {
        if (index >= ordersLength) {
          return result;
        }
        var order = orders[index];
        return result * ((order === 'asc' || order === true) ? 1 : -1);
      }
    }
    return object.index - other.index;
  }
  function deburrLetter(letter) {
    return deburredLetters[letter];
  }
  function escapeHtmlChar(chr) {
    return htmlEscapes[chr];
  }
  function escapeRegExpChar(chr, leadingChar, whitespaceChar) {
    if (leadingChar) {
      chr = regexpEscapes[chr];
    } else if (whitespaceChar) {
      chr = stringEscapes[chr];
    }
    return '\\' + chr;
  }
  function escapeStringChar(chr) {
    return '\\' + stringEscapes[chr];
  }
  function indexOfNaN(array, fromIndex, fromRight) {
    var length = array.length,
        index = fromIndex + (fromRight ? 0 : -1);
    while ((fromRight ? index-- : ++index < length)) {
      var other = array[index];
      if (other !== other) {
        return index;
      }
    }
    return -1;
  }
  function isObjectLike(value) {
    return !!value && typeof value == 'object';
  }
  function isSpace(charCode) {
    return ((charCode <= 160 && (charCode >= 9 && charCode <= 13) || charCode == 32 || charCode == 160) || charCode == 5760 || charCode == 6158 || (charCode >= 8192 && (charCode <= 8202 || charCode == 8232 || charCode == 8233 || charCode == 8239 || charCode == 8287 || charCode == 12288 || charCode == 65279)));
  }
  function replaceHolders(array, placeholder) {
    var index = -1,
        length = array.length,
        resIndex = -1,
        result = [];
    while (++index < length) {
      if (array[index] === placeholder) {
        array[index] = PLACEHOLDER;
        result[++resIndex] = index;
      }
    }
    return result;
  }
  function sortedUniq(array, iteratee) {
    var seen,
        index = -1,
        length = array.length,
        resIndex = -1,
        result = [];
    while (++index < length) {
      var value = array[index],
          computed = iteratee ? iteratee(value, index, array) : value;
      if (!index || seen !== computed) {
        seen = computed;
        result[++resIndex] = value;
      }
    }
    return result;
  }
  function trimmedLeftIndex(string) {
    var index = -1,
        length = string.length;
    while (++index < length && isSpace(string.charCodeAt(index))) {}
    return index;
  }
  function trimmedRightIndex(string) {
    var index = string.length;
    while (index-- && isSpace(string.charCodeAt(index))) {}
    return index;
  }
  function unescapeHtmlChar(chr) {
    return htmlUnescapes[chr];
  }
  function runInContext(context) {
    context = context ? _.defaults(root.Object(), context, _.pick(root, contextProps)) : root;
    var Array = context.Array,
        Date = context.Date,
        Error = context.Error,
        Function = context.Function,
        Math = context.Math,
        Number = context.Number,
        Object = context.Object,
        RegExp = context.RegExp,
        String = context.String,
        TypeError = context.TypeError;
    var arrayProto = Array.prototype,
        objectProto = Object.prototype,
        stringProto = String.prototype;
    var fnToString = Function.prototype.toString;
    var hasOwnProperty = objectProto.hasOwnProperty;
    var idCounter = 0;
    var objToString = objectProto.toString;
    var oldDash = root._;
    var reIsNative = RegExp('^' + fnToString.call(hasOwnProperty).replace(/[\\^$.*+?()[\]{}|]/g, '\\$&').replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$');
    var ArrayBuffer = context.ArrayBuffer,
        clearTimeout = context.clearTimeout,
        parseFloat = context.parseFloat,
        pow = Math.pow,
        propertyIsEnumerable = objectProto.propertyIsEnumerable,
        Set = getNative(context, 'Set'),
        setTimeout = context.setTimeout,
        splice = arrayProto.splice,
        Uint8Array = context.Uint8Array,
        WeakMap = getNative(context, 'WeakMap');
    var nativeCeil = Math.ceil,
        nativeCreate = getNative(Object, 'create'),
        nativeFloor = Math.floor,
        nativeIsArray = getNative(Array, 'isArray'),
        nativeIsFinite = context.isFinite,
        nativeKeys = getNative(Object, 'keys'),
        nativeMax = Math.max,
        nativeMin = Math.min,
        nativeNow = getNative(Date, 'now'),
        nativeParseInt = context.parseInt,
        nativeRandom = Math.random;
    var NEGATIVE_INFINITY = Number.NEGATIVE_INFINITY,
        POSITIVE_INFINITY = Number.POSITIVE_INFINITY;
    var MAX_ARRAY_LENGTH = 4294967295,
        MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1,
        HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1;
    var MAX_SAFE_INTEGER = 9007199254740991;
    var metaMap = WeakMap && new WeakMap;
    var realNames = {};
    function lodash(value) {
      if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) {
        if (value instanceof LodashWrapper) {
          return value;
        }
        if (hasOwnProperty.call(value, '__chain__') && hasOwnProperty.call(value, '__wrapped__')) {
          return wrapperClone(value);
        }
      }
      return new LodashWrapper(value);
    }
    function baseLodash() {}
    function LodashWrapper(value, chainAll, actions) {
      this.__wrapped__ = value;
      this.__actions__ = actions || [];
      this.__chain__ = !!chainAll;
    }
    var support = lodash.support = {};
    lodash.templateSettings = {
      'escape': reEscape,
      'evaluate': reEvaluate,
      'interpolate': reInterpolate,
      'variable': '',
      'imports': {'_': lodash}
    };
    function LazyWrapper(value) {
      this.__wrapped__ = value;
      this.__actions__ = [];
      this.__dir__ = 1;
      this.__filtered__ = false;
      this.__iteratees__ = [];
      this.__takeCount__ = POSITIVE_INFINITY;
      this.__views__ = [];
    }
    function lazyClone() {
      var result = new LazyWrapper(this.__wrapped__);
      result.__actions__ = arrayCopy(this.__actions__);
      result.__dir__ = this.__dir__;
      result.__filtered__ = this.__filtered__;
      result.__iteratees__ = arrayCopy(this.__iteratees__);
      result.__takeCount__ = this.__takeCount__;
      result.__views__ = arrayCopy(this.__views__);
      return result;
    }
    function lazyReverse() {
      if (this.__filtered__) {
        var result = new LazyWrapper(this);
        result.__dir__ = -1;
        result.__filtered__ = true;
      } else {
        result = this.clone();
        result.__dir__ *= -1;
      }
      return result;
    }
    function lazyValue() {
      var array = this.__wrapped__.value(),
          dir = this.__dir__,
          isArr = isArray(array),
          isRight = dir < 0,
          arrLength = isArr ? array.length : 0,
          view = getView(0, arrLength, this.__views__),
          start = view.start,
          end = view.end,
          length = end - start,
          index = isRight ? end : (start - 1),
          iteratees = this.__iteratees__,
          iterLength = iteratees.length,
          resIndex = 0,
          takeCount = nativeMin(length, this.__takeCount__);
      if (!isArr || arrLength < LARGE_ARRAY_SIZE || (arrLength == length && takeCount == length)) {
        return baseWrapperValue((isRight && isArr) ? array.reverse() : array, this.__actions__);
      }
      var result = [];
      outer: while (length-- && resIndex < takeCount) {
        index += dir;
        var iterIndex = -1,
            value = array[index];
        while (++iterIndex < iterLength) {
          var data = iteratees[iterIndex],
              iteratee = data.iteratee,
              type = data.type,
              computed = iteratee(value);
          if (type == LAZY_MAP_FLAG) {
            value = computed;
          } else if (!computed) {
            if (type == LAZY_FILTER_FLAG) {
              continue outer;
            } else {
              break outer;
            }
          }
        }
        result[resIndex++] = value;
      }
      return result;
    }
    function MapCache() {
      this.__data__ = {};
    }
    function mapDelete(key) {
      return this.has(key) && delete this.__data__[key];
    }
    function mapGet(key) {
      return key == '__proto__' ? undefined : this.__data__[key];
    }
    function mapHas(key) {
      return key != '__proto__' && hasOwnProperty.call(this.__data__, key);
    }
    function mapSet(key, value) {
      if (key != '__proto__') {
        this.__data__[key] = value;
      }
      return this;
    }
    function SetCache(values) {
      var length = values ? values.length : 0;
      this.data = {
        'hash': nativeCreate(null),
        'set': new Set
      };
      while (length--) {
        this.push(values[length]);
      }
    }
    function cacheIndexOf(cache, value) {
      var data = cache.data,
          result = (typeof value == 'string' || isObject(value)) ? data.set.has(value) : data.hash[value];
      return result ? 0 : -1;
    }
    function cachePush(value) {
      var data = this.data;
      if (typeof value == 'string' || isObject(value)) {
        data.set.add(value);
      } else {
        data.hash[value] = true;
      }
    }
    function arrayConcat(array, other) {
      var index = -1,
          length = array.length,
          othIndex = -1,
          othLength = other.length,
          result = Array(length + othLength);
      while (++index < length) {
        result[index] = array[index];
      }
      while (++othIndex < othLength) {
        result[index++] = other[othIndex];
      }
      return result;
    }
    function arrayCopy(source, array) {
      var index = -1,
          length = source.length;
      array || (array = Array(length));
      while (++index < length) {
        array[index] = source[index];
      }
      return array;
    }
    function arrayEach(array, iteratee) {
      var index = -1,
          length = array.length;
      while (++index < length) {
        if (iteratee(array[index], index, array) === false) {
          break;
        }
      }
      return array;
    }
    function arrayEachRight(array, iteratee) {
      var length = array.length;
      while (length--) {
        if (iteratee(array[length], length, array) === false) {
          break;
        }
      }
      return array;
    }
    function arrayEvery(array, predicate) {
      var index = -1,
          length = array.length;
      while (++index < length) {
        if (!predicate(array[index], index, array)) {
          return false;
        }
      }
      return true;
    }
    function arrayExtremum(array, iteratee, comparator, exValue) {
      var index = -1,
          length = array.length,
          computed = exValue,
          result = computed;
      while (++index < length) {
        var value = array[index],
            current = +iteratee(value);
        if (comparator(current, computed)) {
          computed = current;
          result = value;
        }
      }
      return result;
    }
    function arrayFilter(array, predicate) {
      var index = -1,
          length = array.length,
          resIndex = -1,
          result = [];
      while (++index < length) {
        var value = array[index];
        if (predicate(value, index, array)) {
          result[++resIndex] = value;
        }
      }
      return result;
    }
    function arrayMap(array, iteratee) {
      var index = -1,
          length = array.length,
          result = Array(length);
      while (++index < length) {
        result[index] = iteratee(array[index], index, array);
      }
      return result;
    }
    function arrayPush(array, values) {
      var index = -1,
          length = values.length,
          offset = array.length;
      while (++index < length) {
        array[offset + index] = values[index];
      }
      return array;
    }
    function arrayReduce(array, iteratee, accumulator, initFromArray) {
      var index = -1,
          length = array.length;
      if (initFromArray && length) {
        accumulator = array[++index];
      }
      while (++index < length) {
        accumulator = iteratee(accumulator, array[index], index, array);
      }
      return accumulator;
    }
    function arrayReduceRight(array, iteratee, accumulator, initFromArray) {
      var length = array.length;
      if (initFromArray && length) {
        accumulator = array[--length];
      }
      while (length--) {
        accumulator = iteratee(accumulator, array[length], length, array);
      }
      return accumulator;
    }
    function arraySome(array, predicate) {
      var index = -1,
          length = array.length;
      while (++index < length) {
        if (predicate(array[index], index, array)) {
          return true;
        }
      }
      return false;
    }
    function arraySum(array, iteratee) {
      var length = array.length,
          result = 0;
      while (length--) {
        result += +iteratee(array[length]) || 0;
      }
      return result;
    }
    function assignDefaults(objectValue, sourceValue) {
      return objectValue === undefined ? sourceValue : objectValue;
    }
    function assignOwnDefaults(objectValue, sourceValue, key, object) {
      return (objectValue === undefined || !hasOwnProperty.call(object, key)) ? sourceValue : objectValue;
    }
    function assignWith(object, source, customizer) {
      var index = -1,
          props = keys(source),
          length = props.length;
      while (++index < length) {
        var key = props[index],
            value = object[key],
            result = customizer(value, source[key], key, object, source);
        if ((result === result ? (result !== value) : (value === value)) || (value === undefined && !(key in object))) {
          object[key] = result;
        }
      }
      return object;
    }
    function baseAssign(object, source) {
      return source == null ? object : baseCopy(source, keys(source), object);
    }
    function baseAt(collection, props) {
      var index = -1,
          isNil = collection == null,
          isArr = !isNil && isArrayLike(collection),
          length = isArr ? collection.length : 0,
          propsLength = props.length,
          result = Array(propsLength);
      while (++index < propsLength) {
        var key = props[index];
        if (isArr) {
          result[index] = isIndex(key, length) ? collection[key] : undefined;
        } else {
          result[index] = isNil ? undefined : collection[key];
        }
      }
      return result;
    }
    function baseCopy(source, props, object) {
      object || (object = {});
      var index = -1,
          length = props.length;
      while (++index < length) {
        var key = props[index];
        object[key] = source[key];
      }
      return object;
    }
    function baseCallback(func, thisArg, argCount) {
      var type = typeof func;
      if (type == 'function') {
        return thisArg === undefined ? func : bindCallback(func, thisArg, argCount);
      }
      if (func == null) {
        return identity;
      }
      if (type == 'object') {
        return baseMatches(func);
      }
      return thisArg === undefined ? property(func) : baseMatchesProperty(func, thisArg);
    }
    function baseClone(value, isDeep, customizer, key, object, stackA, stackB) {
      var result;
      if (customizer) {
        result = object ? customizer(value, key, object) : customizer(value);
      }
      if (result !== undefined) {
        return result;
      }
      if (!isObject(value)) {
        return value;
      }
      var isArr = isArray(value);
      if (isArr) {
        result = initCloneArray(value);
        if (!isDeep) {
          return arrayCopy(value, result);
        }
      } else {
        var tag = objToString.call(value),
            isFunc = tag == funcTag;
        if (tag == objectTag || tag == argsTag || (isFunc && !object)) {
          result = initCloneObject(isFunc ? {} : value);
          if (!isDeep) {
            return baseAssign(result, value);
          }
        } else {
          return cloneableTags[tag] ? initCloneByTag(value, tag, isDeep) : (object ? value : {});
        }
      }
      stackA || (stackA = []);
      stackB || (stackB = []);
      var length = stackA.length;
      while (length--) {
        if (stackA[length] == value) {
          return stackB[length];
        }
      }
      stackA.push(value);
      stackB.push(result);
      (isArr ? arrayEach : baseForOwn)(value, function(subValue, key) {
        result[key] = baseClone(subValue, isDeep, customizer, key, value, stackA, stackB);
      });
      return result;
    }
    var baseCreate = (function() {
      function object() {}
      return function(prototype) {
        if (isObject(prototype)) {
          object.prototype = prototype;
          var result = new object;
          object.prototype = undefined;
        }
        return result || {};
      };
    }());
    function baseDelay(func, wait, args) {
      if (typeof func != 'function') {
        throw new TypeError(FUNC_ERROR_TEXT);
      }
      return setTimeout(function() {
        func.apply(undefined, args);
      }, wait);
    }
    function baseDifference(array, values) {
      var length = array ? array.length : 0,
          result = [];
      if (!length) {
        return result;
      }
      var index = -1,
          indexOf = getIndexOf(),
          isCommon = indexOf == baseIndexOf,
          cache = (isCommon && values.length >= LARGE_ARRAY_SIZE) ? createCache(values) : null,
          valuesLength = values.length;
      if (cache) {
        indexOf = cacheIndexOf;
        isCommon = false;
        values = cache;
      }
      outer: while (++index < length) {
        var value = array[index];
        if (isCommon && value === value) {
          var valuesIndex = valuesLength;
          while (valuesIndex--) {
            if (values[valuesIndex] === value) {
              continue outer;
            }
          }
          result.push(value);
        } else if (indexOf(values, value, 0) < 0) {
          result.push(value);
        }
      }
      return result;
    }
    var baseEach = createBaseEach(baseForOwn);
    var baseEachRight = createBaseEach(baseForOwnRight, true);
    function baseEvery(collection, predicate) {
      var result = true;
      baseEach(collection, function(value, index, collection) {
        result = !!predicate(value, index, collection);
        return result;
      });
      return result;
    }
    function baseExtremum(collection, iteratee, comparator, exValue) {
      var computed = exValue,
          result = computed;
      baseEach(collection, function(value, index, collection) {
        var current = +iteratee(value, index, collection);
        if (comparator(current, computed) || (current === exValue && current === result)) {
          computed = current;
          result = value;
        }
      });
      return result;
    }
    function baseFill(array, value, start, end) {
      var length = array.length;
      start = start == null ? 0 : (+start || 0);
      if (start < 0) {
        start = -start > length ? 0 : (length + start);
      }
      end = (end === undefined || end > length) ? length : (+end || 0);
      if (end < 0) {
        end += length;
      }
      length = start > end ? 0 : (end >>> 0);
      start >>>= 0;
      while (start < length) {
        array[start++] = value;
      }
      return array;
    }
    function baseFilter(collection, predicate) {
      var result = [];
      baseEach(collection, function(value, index, collection) {
        if (predicate(value, index, collection)) {
          result.push(value);
        }
      });
      return result;
    }
    function baseFind(collection, predicate, eachFunc, retKey) {
      var result;
      eachFunc(collection, function(value, key, collection) {
        if (predicate(value, key, collection)) {
          result = retKey ? key : value;
          return false;
        }
      });
      return result;
    }
    function baseFlatten(array, isDeep, isStrict, result) {
      result || (result = []);
      var index = -1,
          length = array.length;
      while (++index < length) {
        var value = array[index];
        if (isObjectLike(value) && isArrayLike(value) && (isStrict || isArray(value) || isArguments(value))) {
          if (isDeep) {
            baseFlatten(value, isDeep, isStrict, result);
          } else {
            arrayPush(result, value);
          }
        } else if (!isStrict) {
          result[result.length] = value;
        }
      }
      return result;
    }
    var baseFor = createBaseFor();
    var baseForRight = createBaseFor(true);
    function baseForIn(object, iteratee) {
      return baseFor(object, iteratee, keysIn);
    }
    function baseForOwn(object, iteratee) {
      return baseFor(object, iteratee, keys);
    }
    function baseForOwnRight(object, iteratee) {
      return baseForRight(object, iteratee, keys);
    }
    function baseFunctions(object, props) {
      var index = -1,
          length = props.length,
          resIndex = -1,
          result = [];
      while (++index < length) {
        var key = props[index];
        if (isFunction(object[key])) {
          result[++resIndex] = key;
        }
      }
      return result;
    }
    function baseGet(object, path, pathKey) {
      if (object == null) {
        return;
      }
      if (pathKey !== undefined && pathKey in toObject(object)) {
        path = [pathKey];
      }
      var index = 0,
          length = path.length;
      while (object != null && index < length) {
        object = object[path[index++]];
      }
      return (index && index == length) ? object : undefined;
    }
    function baseIsEqual(value, other, customizer, isLoose, stackA, stackB) {
      if (value === other) {
        return true;
      }
      if (value == null || other == null || (!isObject(value) && !isObjectLike(other))) {
        return value !== value && other !== other;
      }
      return baseIsEqualDeep(value, other, baseIsEqual, customizer, isLoose, stackA, stackB);
    }
    function baseIsEqualDeep(object, other, equalFunc, customizer, isLoose, stackA, stackB) {
      var objIsArr = isArray(object),
          othIsArr = isArray(other),
          objTag = arrayTag,
          othTag = arrayTag;
      if (!objIsArr) {
        objTag = objToString.call(object);
        if (objTag == argsTag) {
          objTag = objectTag;
        } else if (objTag != objectTag) {
          objIsArr = isTypedArray(object);
        }
      }
      if (!othIsArr) {
        othTag = objToString.call(other);
        if (othTag == argsTag) {
          othTag = objectTag;
        } else if (othTag != objectTag) {
          othIsArr = isTypedArray(other);
        }
      }
      var objIsObj = objTag == objectTag,
          othIsObj = othTag == objectTag,
          isSameTag = objTag == othTag;
      if (isSameTag && !(objIsArr || objIsObj)) {
        return equalByTag(object, other, objTag);
      }
      if (!isLoose) {
        var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),
            othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');
        if (objIsWrapped || othIsWrapped) {
          return equalFunc(objIsWrapped ? object.value() : object, othIsWrapped ? other.value() : other, customizer, isLoose, stackA, stackB);
        }
      }
      if (!isSameTag) {
        return false;
      }
      stackA || (stackA = []);
      stackB || (stackB = []);
      var length = stackA.length;
      while (length--) {
        if (stackA[length] == object) {
          return stackB[length] == other;
        }
      }
      stackA.push(object);
      stackB.push(other);
      var result = (objIsArr ? equalArrays : equalObjects)(object, other, equalFunc, customizer, isLoose, stackA, stackB);
      stackA.pop();
      stackB.pop();
      return result;
    }
    function baseIsMatch(object, matchData, customizer) {
      var index = matchData.length,
          length = index,
          noCustomizer = !customizer;
      if (object == null) {
        return !length;
      }
      object = toObject(object);
      while (index--) {
        var data = matchData[index];
        if ((noCustomizer && data[2]) ? data[1] !== object[data[0]] : !(data[0] in object)) {
          return false;
        }
      }
      while (++index < length) {
        data = matchData[index];
        var key = data[0],
            objValue = object[key],
            srcValue = data[1];
        if (noCustomizer && data[2]) {
          if (objValue === undefined && !(key in object)) {
            return false;
          }
        } else {
          var result = customizer ? customizer(objValue, srcValue, key) : undefined;
          if (!(result === undefined ? baseIsEqual(srcValue, objValue, customizer, true) : result)) {
            return false;
          }
        }
      }
      return true;
    }
    function baseMap(collection, iteratee) {
      var index = -1,
          result = isArrayLike(collection) ? Array(collection.length) : [];
      baseEach(collection, function(value, key, collection) {
        result[++index] = iteratee(value, key, collection);
      });
      return result;
    }
    function baseMatches(source) {
      var matchData = getMatchData(source);
      if (matchData.length == 1 && matchData[0][2]) {
        var key = matchData[0][0],
            value = matchData[0][1];
        return function(object) {
          if (object == null) {
            return false;
          }
          return object[key] === value && (value !== undefined || (key in toObject(object)));
        };
      }
      return function(object) {
        return baseIsMatch(object, matchData);
      };
    }
    function baseMatchesProperty(path, srcValue) {
      var isArr = isArray(path),
          isCommon = isKey(path) && isStrictComparable(srcValue),
          pathKey = (path + '');
      path = toPath(path);
      return function(object) {
        if (object == null) {
          return false;
        }
        var key = pathKey;
        object = toObject(object);
        if ((isArr || !isCommon) && !(key in object)) {
          object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1));
          if (object == null) {
            return false;
          }
          key = last(path);
          object = toObject(object);
        }
        return object[key] === srcValue ? (srcValue !== undefined || (key in object)) : baseIsEqual(srcValue, object[key], undefined, true);
      };
    }
    function baseMerge(object, source, customizer, stackA, stackB) {
      if (!isObject(object)) {
        return object;
      }
      var isSrcArr = isArrayLike(source) && (isArray(source) || isTypedArray(source)),
          props = isSrcArr ? undefined : keys(source);
      arrayEach(props || source, function(srcValue, key) {
        if (props) {
          key = srcValue;
          srcValue = source[key];
        }
        if (isObjectLike(srcValue)) {
          stackA || (stackA = []);
          stackB || (stackB = []);
          baseMergeDeep(object, source, key, baseMerge, customizer, stackA, stackB);
        } else {
          var value = object[key],
              result = customizer ? customizer(value, srcValue, key, object, source) : undefined,
              isCommon = result === undefined;
          if (isCommon) {
            result = srcValue;
          }
          if ((result !== undefined || (isSrcArr && !(key in object))) && (isCommon || (result === result ? (result !== value) : (value === value)))) {
            object[key] = result;
          }
        }
      });
      return object;
    }
    function baseMergeDeep(object, source, key, mergeFunc, customizer, stackA, stackB) {
      var length = stackA.length,
          srcValue = source[key];
      while (length--) {
        if (stackA[length] == srcValue) {
          object[key] = stackB[length];
          return;
        }
      }
      var value = object[key],
          result = customizer ? customizer(value, srcValue, key, object, source) : undefined,
          isCommon = result === undefined;
      if (isCommon) {
        result = srcValue;
        if (isArrayLike(srcValue) && (isArray(srcValue) || isTypedArray(srcValue))) {
          result = isArray(value) ? value : (isArrayLike(value) ? arrayCopy(value) : []);
        } else if (isPlainObject(srcValue) || isArguments(srcValue)) {
          result = isArguments(value) ? toPlainObject(value) : (isPlainObject(value) ? value : {});
        } else {
          isCommon = false;
        }
      }
      stackA.push(srcValue);
      stackB.push(result);
      if (isCommon) {
        object[key] = mergeFunc(result, srcValue, customizer, stackA, stackB);
      } else if (result === result ? (result !== value) : (value === value)) {
        object[key] = result;
      }
    }
    function baseProperty(key) {
      return function(object) {
        return object == null ? undefined : object[key];
      };
    }
    function basePropertyDeep(path) {
      var pathKey = (path + '');
      path = toPath(path);
      return function(object) {
        return baseGet(object, path, pathKey);
      };
    }
    function basePullAt(array, indexes) {
      var length = array ? indexes.length : 0;
      while (length--) {
        var index = indexes[length];
        if (index != previous && isIndex(index)) {
          var previous = index;
          splice.call(array, index, 1);
        }
      }
      return array;
    }
    function baseRandom(min, max) {
      return min + nativeFloor(nativeRandom() * (max - min + 1));
    }
    function baseReduce(collection, iteratee, accumulator, initFromCollection, eachFunc) {
      eachFunc(collection, function(value, index, collection) {
        accumulator = initFromCollection ? (initFromCollection = false, value) : iteratee(accumulator, value, index, collection);
      });
      return accumulator;
    }
    var baseSetData = !metaMap ? identity : function(func, data) {
      metaMap.set(func, data);
      return func;
    };
    function baseSlice(array, start, end) {
      var index = -1,
          length = array.length;
      start = start == null ? 0 : (+start || 0);
      if (start < 0) {
        start = -start > length ? 0 : (length + start);
      }
      end = (end === undefined || end > length) ? length : (+end || 0);
      if (end < 0) {
        end += length;
      }
      length = start > end ? 0 : ((end - start) >>> 0);
      start >>>= 0;
      var result = Array(length);
      while (++index < length) {
        result[index] = array[index + start];
      }
      return result;
    }
    function baseSome(collection, predicate) {
      var result;
      baseEach(collection, function(value, index, collection) {
        result = predicate(value, index, collection);
        return !result;
      });
      return !!result;
    }
    function baseSortBy(array, comparer) {
      var length = array.length;
      array.sort(comparer);
      while (length--) {
        array[length] = array[length].value;
      }
      return array;
    }
    function baseSortByOrder(collection, iteratees, orders) {
      var callback = getCallback(),
          index = -1;
      iteratees = arrayMap(iteratees, function(iteratee) {
        return callback(iteratee);
      });
      var result = baseMap(collection, function(value) {
        var criteria = arrayMap(iteratees, function(iteratee) {
          return iteratee(value);
        });
        return {
          'criteria': criteria,
          'index': ++index,
          'value': value
        };
      });
      return baseSortBy(result, function(object, other) {
        return compareMultiple(object, other, orders);
      });
    }
    function baseSum(collection, iteratee) {
      var result = 0;
      baseEach(collection, function(value, index, collection) {
        result += +iteratee(value, index, collection) || 0;
      });
      return result;
    }
    function baseUniq(array, iteratee) {
      var index = -1,
          indexOf = getIndexOf(),
          length = array.length,
          isCommon = indexOf == baseIndexOf,
          isLarge = isCommon && length >= LARGE_ARRAY_SIZE,
          seen = isLarge ? createCache() : null,
          result = [];
      if (seen) {
        indexOf = cacheIndexOf;
        isCommon = false;
      } else {
        isLarge = false;
        seen = iteratee ? [] : result;
      }
      outer: while (++index < length) {
        var value = array[index],
            computed = iteratee ? iteratee(value, index, array) : value;
        if (isCommon && value === value) {
          var seenIndex = seen.length;
          while (seenIndex--) {
            if (seen[seenIndex] === computed) {
              continue outer;
            }
          }
          if (iteratee) {
            seen.push(computed);
          }
          result.push(value);
        } else if (indexOf(seen, computed, 0) < 0) {
          if (iteratee || isLarge) {
            seen.push(computed);
          }
          result.push(value);
        }
      }
      return result;
    }
    function baseValues(object, props) {
      var index = -1,
          length = props.length,
          result = Array(length);
      while (++index < length) {
        result[index] = object[props[index]];
      }
      return result;
    }
    function baseWhile(array, predicate, isDrop, fromRight) {
      var length = array.length,
          index = fromRight ? length : -1;
      while ((fromRight ? index-- : ++index < length) && predicate(array[index], index, array)) {}
      return isDrop ? baseSlice(array, (fromRight ? 0 : index), (fromRight ? index + 1 : length)) : baseSlice(array, (fromRight ? index + 1 : 0), (fromRight ? length : index));
    }
    function baseWrapperValue(value, actions) {
      var result = value;
      if (result instanceof LazyWrapper) {
        result = result.value();
      }
      var index = -1,
          length = actions.length;
      while (++index < length) {
        var action = actions[index];
        result = action.func.apply(action.thisArg, arrayPush([result], action.args));
      }
      return result;
    }
    function binaryIndex(array, value, retHighest) {
      var low = 0,
          high = array ? array.length : low;
      if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) {
        while (low < high) {
          var mid = (low + high) >>> 1,
              computed = array[mid];
          if ((retHighest ? (computed <= value) : (computed < value)) && computed !== null) {
            low = mid + 1;
          } else {
            high = mid;
          }
        }
        return high;
      }
      return binaryIndexBy(array, value, identity, retHighest);
    }
    function binaryIndexBy(array, value, iteratee, retHighest) {
      value = iteratee(value);
      var low = 0,
          high = array ? array.length : 0,
          valIsNaN = value !== value,
          valIsNull = value === null,
          valIsUndef = value === undefined;
      while (low < high) {
        var mid = nativeFloor((low + high) / 2),
            computed = iteratee(array[mid]),
            isDef = computed !== undefined,
            isReflexive = computed === computed;
        if (valIsNaN) {
          var setLow = isReflexive || retHighest;
        } else if (valIsNull) {
          setLow = isReflexive && isDef && (retHighest || computed != null);
        } else if (valIsUndef) {
          setLow = isReflexive && (retHighest || isDef);
        } else if (computed == null) {
          setLow = false;
        } else {
          setLow = retHighest ? (computed <= value) : (computed < value);
        }
        if (setLow) {
          low = mid + 1;
        } else {
          high = mid;
        }
      }
      return nativeMin(high, MAX_ARRAY_INDEX);
    }
    function bindCallback(func, thisArg, argCount) {
      if (typeof func != 'function') {
        return identity;
      }
      if (thisArg === undefined) {
        return func;
      }
      switch (argCount) {
        case 1:
          return function(value) {
            return func.call(thisArg, value);
          };
        case 3:
          return function(value, index, collection) {
            return func.call(thisArg, value, index, collection);
          };
        case 4:
          return function(accumulator, value, index, collection) {
            return func.call(thisArg, accumulator, value, index, collection);
          };
        case 5:
          return function(value, other, key, object, source) {
            return func.call(thisArg, value, other, key, object, source);
          };
      }
      return function() {
        return func.apply(thisArg, arguments);
      };
    }
    function bufferClone(buffer) {
      var result = new ArrayBuffer(buffer.byteLength),
          view = new Uint8Array(result);
      view.set(new Uint8Array(buffer));
      return result;
    }
    function composeArgs(args, partials, holders) {
      var holdersLength = holders.length,
          argsIndex = -1,
          argsLength = nativeMax(args.length - holdersLength, 0),
          leftIndex = -1,
          leftLength = partials.length,
          result = Array(leftLength + argsLength);
      while (++leftIndex < leftLength) {
        result[leftIndex] = partials[leftIndex];
      }
      while (++argsIndex < holdersLength) {
        result[holders[argsIndex]] = args[argsIndex];
      }
      while (argsLength--) {
        result[leftIndex++] = args[argsIndex++];
      }
      return result;
    }
    function composeArgsRight(args, partials, holders) {
      var holdersIndex = -1,
          holdersLength = holders.length,
          argsIndex = -1,
          argsLength = nativeMax(args.length - holdersLength, 0),
          rightIndex = -1,
          rightLength = partials.length,
          result = Array(argsLength + rightLength);
      while (++argsIndex < argsLength) {
        result[argsIndex] = args[argsIndex];
      }
      var offset = argsIndex;
      while (++rightIndex < rightLength) {
        result[offset + rightIndex] = partials[rightIndex];
      }
      while (++holdersIndex < holdersLength) {
        result[offset + holders[holdersIndex]] = args[argsIndex++];
      }
      return result;
    }
    function createAggregator(setter, initializer) {
      return function(collection, iteratee, thisArg) {
        var result = initializer ? initializer() : {};
        iteratee = getCallback(iteratee, thisArg, 3);
        if (isArray(collection)) {
          var index = -1,
              length = collection.length;
          while (++index < length) {
            var value = collection[index];
            setter(result, value, iteratee(value, index, collection), collection);
          }
        } else {
          baseEach(collection, function(value, key, collection) {
            setter(result, value, iteratee(value, key, collection), collection);
          });
        }
        return result;
      };
    }
    function createAssigner(assigner) {
      return restParam(function(object, sources) {
        var index = -1,
            length = object == null ? 0 : sources.length,
            customizer = length > 2 ? sources[length - 2] : undefined,
            guard = length > 2 ? sources[2] : undefined,
            thisArg = length > 1 ? sources[length - 1] : undefined;
        if (typeof customizer == 'function') {
          customizer = bindCallback(customizer, thisArg, 5);
          length -= 2;
        } else {
          customizer = typeof thisArg == 'function' ? thisArg : undefined;
          length -= (customizer ? 1 : 0);
        }
        if (guard && isIterateeCall(sources[0], sources[1], guard)) {
          customizer = length < 3 ? undefined : customizer;
          length = 1;
        }
        while (++index < length) {
          var source = sources[index];
          if (source) {
            assigner(object, source, customizer);
          }
        }
        return object;
      });
    }
    function createBaseEach(eachFunc, fromRight) {
      return function(collection, iteratee) {
        var length = collection ? getLength(collection) : 0;
        if (!isLength(length)) {
          return eachFunc(collection, iteratee);
        }
        var index = fromRight ? length : -1,
            iterable = toObject(collection);
        while ((fromRight ? index-- : ++index < length)) {
          if (iteratee(iterable[index], index, iterable) === false) {
            break;
          }
        }
        return collection;
      };
    }
    function createBaseFor(fromRight) {
      return function(object, iteratee, keysFunc) {
        var iterable = toObject(object),
            props = keysFunc(object),
            length = props.length,
            index = fromRight ? length : -1;
        while ((fromRight ? index-- : ++index < length)) {
          var key = props[index];
          if (iteratee(iterable[key], key, iterable) === false) {
            break;
          }
        }
        return object;
      };
    }
    function createBindWrapper(func, thisArg) {
      var Ctor = createCtorWrapper(func);
      function wrapper() {
        var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
        return fn.apply(thisArg, arguments);
      }
      return wrapper;
    }
    function createCache(values) {
      return (nativeCreate && Set) ? new SetCache(values) : null;
    }
    function createCompounder(callback) {
      return function(string) {
        var index = -1,
            array = words(deburr(string)),
            length = array.length,
            result = '';
        while (++index < length) {
          result = callback(result, array[index], index);
        }
        return result;
      };
    }
    function createCtorWrapper(Ctor) {
      return function() {
        var args = arguments;
        switch (args.length) {
          case 0:
            return new Ctor;
          case 1:
            return new Ctor(args[0]);
          case 2:
            return new Ctor(args[0], args[1]);
          case 3:
            return new Ctor(args[0], args[1], args[2]);
          case 4:
            return new Ctor(args[0], args[1], args[2], args[3]);
          case 5:
            return new Ctor(args[0], args[1], args[2], args[3], args[4]);
          case 6:
            return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]);
          case 7:
            return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
        }
        var thisBinding = baseCreate(Ctor.prototype),
            result = Ctor.apply(thisBinding, args);
        return isObject(result) ? result : thisBinding;
      };
    }
    function createCurry(flag) {
      function curryFunc(func, arity, guard) {
        if (guard && isIterateeCall(func, arity, guard)) {
          arity = undefined;
        }
        var result = createWrapper(func, flag, undefined, undefined, undefined, undefined, undefined, arity);
        result.placeholder = curryFunc.placeholder;
        return result;
      }
      return curryFunc;
    }
    function createDefaults(assigner, customizer) {
      return restParam(function(args) {
        var object = args[0];
        if (object == null) {
          return object;
        }
        args.push(customizer);
        return assigner.apply(undefined, args);
      });
    }
    function createExtremum(comparator, exValue) {
      return function(collection, iteratee, thisArg) {
        if (thisArg && isIterateeCall(collection, iteratee, thisArg)) {
          iteratee = undefined;
        }
        iteratee = getCallback(iteratee, thisArg, 3);
        if (iteratee.length == 1) {
          collection = isArray(collection) ? collection : toIterable(collection);
          var result = arrayExtremum(collection, iteratee, comparator, exValue);
          if (!(collection.length && result === exValue)) {
            return result;
          }
        }
        return baseExtremum(collection, iteratee, comparator, exValue);
      };
    }
    function createFind(eachFunc, fromRight) {
      return function(collection, predicate, thisArg) {
        predicate = getCallback(predicate, thisArg, 3);
        if (isArray(collection)) {
          var index = baseFindIndex(collection, predicate, fromRight);
          return index > -1 ? collection[index] : undefined;
        }
        return baseFind(collection, predicate, eachFunc);
      };
    }
    function createFindIndex(fromRight) {
      return function(array, predicate, thisArg) {
        if (!(array && array.length)) {
          return -1;
        }
        predicate = getCallback(predicate, thisArg, 3);
        return baseFindIndex(array, predicate, fromRight);
      };
    }
    function createFindKey(objectFunc) {
      return function(object, predicate, thisArg) {
        predicate = getCallback(predicate, thisArg, 3);
        return baseFind(object, predicate, objectFunc, true);
      };
    }
    function createFlow(fromRight) {
      return function() {
        var wrapper,
            length = arguments.length,
            index = fromRight ? length : -1,
            leftIndex = 0,
            funcs = Array(length);
        while ((fromRight ? index-- : ++index < length)) {
          var func = funcs[leftIndex++] = arguments[index];
          if (typeof func != 'function') {
            throw new TypeError(FUNC_ERROR_TEXT);
          }
          if (!wrapper && LodashWrapper.prototype.thru && getFuncName(func) == 'wrapper') {
            wrapper = new LodashWrapper([], true);
          }
        }
        index = wrapper ? -1 : length;
        while (++index < length) {
          func = funcs[index];
          var funcName = getFuncName(func),
              data = funcName == 'wrapper' ? getData(func) : undefined;
          if (data && isLaziable(data[0]) && data[1] == (ARY_FLAG | CURRY_FLAG | PARTIAL_FLAG | REARG_FLAG) && !data[4].length && data[9] == 1) {
            wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]);
          } else {
            wrapper = (func.length == 1 && isLaziable(func)) ? wrapper[funcName]() : wrapper.thru(func);
          }
        }
        return function() {
          var args = arguments,
              value = args[0];
          if (wrapper && args.length == 1 && isArray(value) && value.length >= LARGE_ARRAY_SIZE) {
            return wrapper.plant(value).value();
          }
          var index = 0,
              result = length ? funcs[index].apply(this, args) : value;
          while (++index < length) {
            result = funcs[index].call(this, result);
          }
          return result;
        };
      };
    }
    function createForEach(arrayFunc, eachFunc) {
      return function(collection, iteratee, thisArg) {
        return (typeof iteratee == 'function' && thisArg === undefined && isArray(collection)) ? arrayFunc(collection, iteratee) : eachFunc(collection, bindCallback(iteratee, thisArg, 3));
      };
    }
    function createForIn(objectFunc) {
      return function(object, iteratee, thisArg) {
        if (typeof iteratee != 'function' || thisArg !== undefined) {
          iteratee = bindCallback(iteratee, thisArg, 3);
        }
        return objectFunc(object, iteratee, keysIn);
      };
    }
    function createForOwn(objectFunc) {
      return function(object, iteratee, thisArg) {
        if (typeof iteratee != 'function' || thisArg !== undefined) {
          iteratee = bindCallback(iteratee, thisArg, 3);
        }
        return objectFunc(object, iteratee);
      };
    }
    function createObjectMapper(isMapKeys) {
      return function(object, iteratee, thisArg) {
        var result = {};
        iteratee = getCallback(iteratee, thisArg, 3);
        baseForOwn(object, function(value, key, object) {
          var mapped = iteratee(value, key, object);
          key = isMapKeys ? mapped : key;
          value = isMapKeys ? value : mapped;
          result[key] = value;
        });
        return result;
      };
    }
    function createPadDir(fromRight) {
      return function(string, length, chars) {
        string = baseToString(string);
        return (fromRight ? string : '') + createPadding(string, length, chars) + (fromRight ? '' : string);
      };
    }
    function createPartial(flag) {
      var partialFunc = restParam(function(func, partials) {
        var holders = replaceHolders(partials, partialFunc.placeholder);
        return createWrapper(func, flag, undefined, partials, holders);
      });
      return partialFunc;
    }
    function createReduce(arrayFunc, eachFunc) {
      return function(collection, iteratee, accumulator, thisArg) {
        var initFromArray = arguments.length < 3;
        return (typeof iteratee == 'function' && thisArg === undefined && isArray(collection)) ? arrayFunc(collection, iteratee, accumulator, initFromArray) : baseReduce(collection, getCallback(iteratee, thisArg, 4), accumulator, initFromArray, eachFunc);
      };
    }
    function createHybridWrapper(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) {
      var isAry = bitmask & ARY_FLAG,
          isBind = bitmask & BIND_FLAG,
          isBindKey = bitmask & BIND_KEY_FLAG,
          isCurry = bitmask & CURRY_FLAG,
          isCurryBound = bitmask & CURRY_BOUND_FLAG,
          isCurryRight = bitmask & CURRY_RIGHT_FLAG,
          Ctor = isBindKey ? undefined : createCtorWrapper(func);
      function wrapper() {
        var length = arguments.length,
            index = length,
            args = Array(length);
        while (index--) {
          args[index] = arguments[index];
        }
        if (partials) {
          args = composeArgs(args, partials, holders);
        }
        if (partialsRight) {
          args = composeArgsRight(args, partialsRight, holdersRight);
        }
        if (isCurry || isCurryRight) {
          var placeholder = wrapper.placeholder,
              argsHolders = replaceHolders(args, placeholder);
          length -= argsHolders.length;
          if (length < arity) {
            var newArgPos = argPos ? arrayCopy(argPos) : undefined,
                newArity = nativeMax(arity - length, 0),
                newsHolders = isCurry ? argsHolders : undefined,
                newHoldersRight = isCurry ? undefined : argsHolders,
                newPartials = isCurry ? args : undefined,
                newPartialsRight = isCurry ? undefined : args;
            bitmask |= (isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG);
            bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG);
            if (!isCurryBound) {
              bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG);
            }
            var newData = [func, bitmask, thisArg, newPartials, newsHolders, newPartialsRight, newHoldersRight, newArgPos, ary, newArity],
                result = createHybridWrapper.apply(undefined, newData);
            if (isLaziable(func)) {
              setData(result, newData);
            }
            result.placeholder = placeholder;
            return result;
          }
        }
        var thisBinding = isBind ? thisArg : this,
            fn = isBindKey ? thisBinding[func] : func;
        if (argPos) {
          args = reorder(args, argPos);
        }
        if (isAry && ary < args.length) {
          args.length = ary;
        }
        if (this && this !== root && this instanceof wrapper) {
          fn = Ctor || createCtorWrapper(func);
        }
        return fn.apply(thisBinding, args);
      }
      return wrapper;
    }
    function createPadding(string, length, chars) {
      var strLength = string.length;
      length = +length;
      if (strLength >= length || !nativeIsFinite(length)) {
        return '';
      }
      var padLength = length - strLength;
      chars = chars == null ? ' ' : (chars + '');
      return repeat(chars, nativeCeil(padLength / chars.length)).slice(0, padLength);
    }
    function createPartialWrapper(func, bitmask, thisArg, partials) {
      var isBind = bitmask & BIND_FLAG,
          Ctor = createCtorWrapper(func);
      function wrapper() {
        var argsIndex = -1,
            argsLength = arguments.length,
            leftIndex = -1,
            leftLength = partials.length,
            args = Array(leftLength + argsLength);
        while (++leftIndex < leftLength) {
          args[leftIndex] = partials[leftIndex];
        }
        while (argsLength--) {
          args[leftIndex++] = arguments[++argsIndex];
        }
        var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
        return fn.apply(isBind ? thisArg : this, args);
      }
      return wrapper;
    }
    function createRound(methodName) {
      var func = Math[methodName];
      return function(number, precision) {
        precision = precision === undefined ? 0 : (+precision || 0);
        if (precision) {
          precision = pow(10, precision);
          return func(number * precision) / precision;
        }
        return func(number);
      };
    }
    function createSortedIndex(retHighest) {
      return function(array, value, iteratee, thisArg) {
        var callback = getCallback(iteratee);
        return (iteratee == null && callback === baseCallback) ? binaryIndex(array, value, retHighest) : binaryIndexBy(array, value, callback(iteratee, thisArg, 1), retHighest);
      };
    }
    function createWrapper(func, bitmask, thisArg, partials, holders, argPos, ary, arity) {
      var isBindKey = bitmask & BIND_KEY_FLAG;
      if (!isBindKey && typeof func != 'function') {
        throw new TypeError(FUNC_ERROR_TEXT);
      }
      var length = partials ? partials.length : 0;
      if (!length) {
        bitmask &= ~(PARTIAL_FLAG | PARTIAL_RIGHT_FLAG);
        partials = holders = undefined;
      }
      length -= (holders ? holders.length : 0);
      if (bitmask & PARTIAL_RIGHT_FLAG) {
        var partialsRight = partials,
            holdersRight = holders;
        partials = holders = undefined;
      }
      var data = isBindKey ? undefined : getData(func),
          newData = [func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity];
      if (data) {
        mergeData(newData, data);
        bitmask = newData[1];
        arity = newData[9];
      }
      newData[9] = arity == null ? (isBindKey ? 0 : func.length) : (nativeMax(arity - length, 0) || 0);
      if (bitmask == BIND_FLAG) {
        var result = createBindWrapper(newData[0], newData[2]);
      } else if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !newData[4].length) {
        result = createPartialWrapper.apply(undefined, newData);
      } else {
        result = createHybridWrapper.apply(undefined, newData);
      }
      var setter = data ? baseSetData : setData;
      return setter(result, newData);
    }
    function equalArrays(array, other, equalFunc, customizer, isLoose, stackA, stackB) {
      var index = -1,
          arrLength = array.length,
          othLength = other.length;
      if (arrLength != othLength && !(isLoose && othLength > arrLength)) {
        return false;
      }
      while (++index < arrLength) {
        var arrValue = array[index],
            othValue = other[index],
            result = customizer ? customizer(isLoose ? othValue : arrValue, isLoose ? arrValue : othValue, index) : undefined;
        if (result !== undefined) {
          if (result) {
            continue;
          }
          return false;
        }
        if (isLoose) {
          if (!arraySome(other, function(othValue) {
            return arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB);
          })) {
            return false;
          }
        } else if (!(arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB))) {
          return false;
        }
      }
      return true;
    }
    function equalByTag(object, other, tag) {
      switch (tag) {
        case boolTag:
        case dateTag:
          return +object == +other;
        case errorTag:
          return object.name == other.name && object.message == other.message;
        case numberTag:
          return (object != +object) ? other != +other : object == +other;
        case regexpTag:
        case stringTag:
          return object == (other + '');
      }
      return false;
    }
    function equalObjects(object, other, equalFunc, customizer, isLoose, stackA, stackB) {
      var objProps = keys(object),
          objLength = objProps.length,
          othProps = keys(other),
          othLength = othProps.length;
      if (objLength != othLength && !isLoose) {
        return false;
      }
      var index = objLength;
      while (index--) {
        var key = objProps[index];
        if (!(isLoose ? key in other : hasOwnProperty.call(other, key))) {
          return false;
        }
      }
      var skipCtor = isLoose;
      while (++index < objLength) {
        key = objProps[index];
        var objValue = object[key],
            othValue = other[key],
            result = customizer ? customizer(isLoose ? othValue : objValue, isLoose ? objValue : othValue, key) : undefined;
        if (!(result === undefined ? equalFunc(objValue, othValue, customizer, isLoose, stackA, stackB) : result)) {
          return false;
        }
        skipCtor || (skipCtor = key == 'constructor');
      }
      if (!skipCtor) {
        var objCtor = object.constructor,
            othCtor = other.constructor;
        if (objCtor != othCtor && ('constructor' in object && 'constructor' in other) && !(typeof objCtor == 'function' && objCtor instanceof objCtor && typeof othCtor == 'function' && othCtor instanceof othCtor)) {
          return false;
        }
      }
      return true;
    }
    function getCallback(func, thisArg, argCount) {
      var result = lodash.callback || callback;
      result = result === callback ? baseCallback : result;
      return argCount ? result(func, thisArg, argCount) : result;
    }
    var getData = !metaMap ? noop : function(func) {
      return metaMap.get(func);
    };
    function getFuncName(func) {
      var result = func.name,
          array = realNames[result],
          length = array ? array.length : 0;
      while (length--) {
        var data = array[length],
            otherFunc = data.func;
        if (otherFunc == null || otherFunc == func) {
          return data.name;
        }
      }
      return result;
    }
    function getIndexOf(collection, target, fromIndex) {
      var result = lodash.indexOf || indexOf;
      result = result === indexOf ? baseIndexOf : result;
      return collection ? result(collection, target, fromIndex) : result;
    }
    var getLength = baseProperty('length');
    function getMatchData(object) {
      var result = pairs(object),
          length = result.length;
      while (length--) {
        result[length][2] = isStrictComparable(result[length][1]);
      }
      return result;
    }
    function getNative(object, key) {
      var value = object == null ? undefined : object[key];
      return isNative(value) ? value : undefined;
    }
    function getView(start, end, transforms) {
      var index = -1,
          length = transforms.length;
      while (++index < length) {
        var data = transforms[index],
            size = data.size;
        switch (data.type) {
          case 'drop':
            start += size;
            break;
          case 'dropRight':
            end -= size;
            break;
          case 'take':
            end = nativeMin(end, start + size);
            break;
          case 'takeRight':
            start = nativeMax(start, end - size);
            break;
        }
      }
      return {
        'start': start,
        'end': end
      };
    }
    function initCloneArray(array) {
      var length = array.length,
          result = new array.constructor(length);
      if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) {
        result.index = array.index;
        result.input = array.input;
      }
      return result;
    }
    function initCloneObject(object) {
      var Ctor = object.constructor;
      if (!(typeof Ctor == 'function' && Ctor instanceof Ctor)) {
        Ctor = Object;
      }
      return new Ctor;
    }
    function initCloneByTag(object, tag, isDeep) {
      var Ctor = object.constructor;
      switch (tag) {
        case arrayBufferTag:
          return bufferClone(object);
        case boolTag:
        case dateTag:
          return new Ctor(+object);
        case float32Tag:
        case float64Tag:
        case int8Tag:
        case int16Tag:
        case int32Tag:
        case uint8Tag:
        case uint8ClampedTag:
        case uint16Tag:
        case uint32Tag:
          var buffer = object.buffer;
          return new Ctor(isDeep ? bufferClone(buffer) : buffer, object.byteOffset, object.length);
        case numberTag:
        case stringTag:
          return new Ctor(object);
        case regexpTag:
          var result = new Ctor(object.source, reFlags.exec(object));
          result.lastIndex = object.lastIndex;
      }
      return result;
    }
    function invokePath(object, path, args) {
      if (object != null && !isKey(path, object)) {
        path = toPath(path);
        object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1));
        path = last(path);
      }
      var func = object == null ? object : object[path];
      return func == null ? undefined : func.apply(object, args);
    }
    function isArrayLike(value) {
      return value != null && isLength(getLength(value));
    }
    function isIndex(value, length) {
      value = (typeof value == 'number' || reIsUint.test(value)) ? +value : -1;
      length = length == null ? MAX_SAFE_INTEGER : length;
      return value > -1 && value % 1 == 0 && value < length;
    }
    function isIterateeCall(value, index, object) {
      if (!isObject(object)) {
        return false;
      }
      var type = typeof index;
      if (type == 'number' ? (isArrayLike(object) && isIndex(index, object.length)) : (type == 'string' && index in object)) {
        var other = object[index];
        return value === value ? (value === other) : (other !== other);
      }
      return false;
    }
    function isKey(value, object) {
      var type = typeof value;
      if ((type == 'string' && reIsPlainProp.test(value)) || type == 'number') {
        return true;
      }
      if (isArray(value)) {
        return false;
      }
      var result = !reIsDeepProp.test(value);
      return result || (object != null && value in toObject(object));
    }
    function isLaziable(func) {
      var funcName = getFuncName(func);
      if (!(funcName in LazyWrapper.prototype)) {
        return false;
      }
      var other = lodash[funcName];
      if (func === other) {
        return true;
      }
      var data = getData(other);
      return !!data && func === data[0];
    }
    function isLength(value) {
      return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
    }
    function isStrictComparable(value) {
      return value === value && !isObject(value);
    }
    function mergeData(data, source) {
      var bitmask = data[1],
          srcBitmask = source[1],
          newBitmask = bitmask | srcBitmask,
          isCommon = newBitmask < ARY_FLAG;
      var isCombo = (srcBitmask == ARY_FLAG && bitmask == CURRY_FLAG) || (srcBitmask == ARY_FLAG && bitmask == REARG_FLAG && data[7].length <= source[8]) || (srcBitmask == (ARY_FLAG | REARG_FLAG) && bitmask == CURRY_FLAG);
      if (!(isCommon || isCombo)) {
        return data;
      }
      if (srcBitmask & BIND_FLAG) {
        data[2] = source[2];
        newBitmask |= (bitmask & BIND_FLAG) ? 0 : CURRY_BOUND_FLAG;
      }
      var value = source[3];
      if (value) {
        var partials = data[3];
        data[3] = partials ? composeArgs(partials, value, source[4]) : arrayCopy(value);
        data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : arrayCopy(source[4]);
      }
      value = source[5];
      if (value) {
        partials = data[5];
        data[5] = partials ? composeArgsRight(partials, value, source[6]) : arrayCopy(value);
        data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : arrayCopy(source[6]);
      }
      value = source[7];
      if (value) {
        data[7] = arrayCopy(value);
      }
      if (srcBitmask & ARY_FLAG) {
        data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]);
      }
      if (data[9] == null) {
        data[9] = source[9];
      }
      data[0] = source[0];
      data[1] = newBitmask;
      return data;
    }
    function mergeDefaults(objectValue, sourceValue) {
      return objectValue === undefined ? sourceValue : merge(objectValue, sourceValue, mergeDefaults);
    }
    function pickByArray(object, props) {
      object = toObject(object);
      var index = -1,
          length = props.length,
          result = {};
      while (++index < length) {
        var key = props[index];
        if (key in object) {
          result[key] = object[key];
        }
      }
      return result;
    }
    function pickByCallback(object, predicate) {
      var result = {};
      baseForIn(object, function(value, key, object) {
        if (predicate(value, key, object)) {
          result[key] = value;
        }
      });
      return result;
    }
    function reorder(array, indexes) {
      var arrLength = array.length,
          length = nativeMin(indexes.length, arrLength),
          oldArray = arrayCopy(array);
      while (length--) {
        var index = indexes[length];
        array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined;
      }
      return array;
    }
    var setData = (function() {
      var count = 0,
          lastCalled = 0;
      return function(key, value) {
        var stamp = now(),
            remaining = HOT_SPAN - (stamp - lastCalled);
        lastCalled = stamp;
        if (remaining > 0) {
          if (++count >= HOT_COUNT) {
            return key;
          }
        } else {
          count = 0;
        }
        return baseSetData(key, value);
      };
    }());
    function shimKeys(object) {
      var props = keysIn(object),
          propsLength = props.length,
          length = propsLength && object.length;
      var allowIndexes = !!length && isLength(length) && (isArray(object) || isArguments(object));
      var index = -1,
          result = [];
      while (++index < propsLength) {
        var key = props[index];
        if ((allowIndexes && isIndex(key, length)) || hasOwnProperty.call(object, key)) {
          result.push(key);
        }
      }
      return result;
    }
    function toIterable(value) {
      if (value == null) {
        return [];
      }
      if (!isArrayLike(value)) {
        return values(value);
      }
      return isObject(value) ? value : Object(value);
    }
    function toObject(value) {
      return isObject(value) ? value : Object(value);
    }
    function toPath(value) {
      if (isArray(value)) {
        return value;
      }
      var result = [];
      baseToString(value).replace(rePropName, function(match, number, quote, string) {
        result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match));
      });
      return result;
    }
    function wrapperClone(wrapper) {
      return wrapper instanceof LazyWrapper ? wrapper.clone() : new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__, arrayCopy(wrapper.__actions__));
    }
    function chunk(array, size, guard) {
      if (guard ? isIterateeCall(array, size, guard) : size == null) {
        size = 1;
      } else {
        size = nativeMax(nativeFloor(size) || 1, 1);
      }
      var index = 0,
          length = array ? array.length : 0,
          resIndex = -1,
          result = Array(nativeCeil(length / size));
      while (index < length) {
        result[++resIndex] = baseSlice(array, index, (index += size));
      }
      return result;
    }
    function compact(array) {
      var index = -1,
          length = array ? array.length : 0,
          resIndex = -1,
          result = [];
      while (++index < length) {
        var value = array[index];
        if (value) {
          result[++resIndex] = value;
        }
      }
      return result;
    }
    var difference = restParam(function(array, values) {
      return (isObjectLike(array) && isArrayLike(array)) ? baseDifference(array, baseFlatten(values, false, true)) : [];
    });
    function drop(array, n, guard) {
      var length = array ? array.length : 0;
      if (!length) {
        return [];
      }
      if (guard ? isIterateeCall(array, n, guard) : n == null) {
        n = 1;
      }
      return baseSlice(array, n < 0 ? 0 : n);
    }
    function dropRight(array, n, guard) {
      var length = array ? array.length : 0;
      if (!length) {
        return [];
      }
      if (guard ? isIterateeCall(array, n, guard) : n == null) {
        n = 1;
      }
      n = length - (+n || 0);
      return baseSlice(array, 0, n < 0 ? 0 : n);
    }
    function dropRightWhile(array, predicate, thisArg) {
      return (array && array.length) ? baseWhile(array, getCallback(predicate, thisArg, 3), true, true) : [];
    }
    function dropWhile(array, predicate, thisArg) {
      return (array && array.length) ? baseWhile(array, getCallback(predicate, thisArg, 3), true) : [];
    }
    function fill(array, value, start, end) {
      var length = array ? array.length : 0;
      if (!length) {
        return [];
      }
      if (start && typeof start != 'number' && isIterateeCall(array, value, start)) {
        start = 0;
        end = length;
      }
      return baseFill(array, value, start, end);
    }
    var findIndex = createFindIndex();
    var findLastIndex = createFindIndex(true);
    function first(array) {
      return array ? array[0] : undefined;
    }
    function flatten(array, isDeep, guard) {
      var length = array ? array.length : 0;
      if (guard && isIterateeCall(array, isDeep, guard)) {
        isDeep = false;
      }
      return length ? baseFlatten(array, isDeep) : [];
    }
    function flattenDeep(array) {
      var length = array ? array.length : 0;
      return length ? baseFlatten(array, true) : [];
    }
    function indexOf(array, value, fromIndex) {
      var length = array ? array.length : 0;
      if (!length) {
        return -1;
      }
      if (typeof fromIndex == 'number') {
        fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex;
      } else if (fromIndex) {
        var index = binaryIndex(array, value);
        if (index < length && (value === value ? (value === array[index]) : (array[index] !== array[index]))) {
          return index;
        }
        return -1;
      }
      return baseIndexOf(array, value, fromIndex || 0);
    }
    function initial(array) {
      return dropRight(array, 1);
    }
    var intersection = restParam(function(arrays) {
      var othLength = arrays.length,
          othIndex = othLength,
          caches = Array(length),
          indexOf = getIndexOf(),
          isCommon = indexOf == baseIndexOf,
          result = [];
      while (othIndex--) {
        var value = arrays[othIndex] = isArrayLike(value = arrays[othIndex]) ? value : [];
        caches[othIndex] = (isCommon && value.length >= 120) ? createCache(othIndex && value) : null;
      }
      var array = arrays[0],
          index = -1,
          length = array ? array.length : 0,
          seen = caches[0];
      outer: while (++index < length) {
        value = array[index];
        if ((seen ? cacheIndexOf(seen, value) : indexOf(result, value, 0)) < 0) {
          var othIndex = othLength;
          while (--othIndex) {
            var cache = caches[othIndex];
            if ((cache ? cacheIndexOf(cache, value) : indexOf(arrays[othIndex], value, 0)) < 0) {
              continue outer;
            }
          }
          if (seen) {
            seen.push(value);
          }
          result.push(value);
        }
      }
      return result;
    });
    function last(array) {
      var length = array ? array.length : 0;
      return length ? array[length - 1] : undefined;
    }
    function lastIndexOf(array, value, fromIndex) {
      var length = array ? array.length : 0;
      if (!length) {
        return -1;
      }
      var index = length;
      if (typeof fromIndex == 'number') {
        index = (fromIndex < 0 ? nativeMax(length + fromIndex, 0) : nativeMin(fromIndex || 0, length - 1)) + 1;
      } else if (fromIndex) {
        index = binaryIndex(array, value, true) - 1;
        var other = array[index];
        if (value === value ? (value === other) : (other !== other)) {
          return index;
        }
        return -1;
      }
      if (value !== value) {
        return indexOfNaN(array, index, true);
      }
      while (index--) {
        if (array[index] === value) {
          return index;
        }
      }
      return -1;
    }
    function pull() {
      var args = arguments,
          array = args[0];
      if (!(array && array.length)) {
        return array;
      }
      var index = 0,
          indexOf = getIndexOf(),
          length = args.length;
      while (++index < length) {
        var fromIndex = 0,
            value = args[index];
        while ((fromIndex = indexOf(array, value, fromIndex)) > -1) {
          splice.call(array, fromIndex, 1);
        }
      }
      return array;
    }
    var pullAt = restParam(function(array, indexes) {
      indexes = baseFlatten(indexes);
      var result = baseAt(array, indexes);
      basePullAt(array, indexes.sort(baseCompareAscending));
      return result;
    });
    function remove(array, predicate, thisArg) {
      var result = [];
      if (!(array && array.length)) {
        return result;
      }
      var index = -1,
          indexes = [],
          length = array.length;
      predicate = getCallback(predicate, thisArg, 3);
      while (++index < length) {
        var value = array[index];
        if (predicate(value, index, array)) {
          result.push(value);
          indexes.push(index);
        }
      }
      basePullAt(array, indexes);
      return result;
    }
    function rest(array) {
      return drop(array, 1);
    }
    function slice(array, start, end) {
      var length = array ? array.length : 0;
      if (!length) {
        return [];
      }
      if (end && typeof end != 'number' && isIterateeCall(array, start, end)) {
        start = 0;
        end = length;
      }
      return baseSlice(array, start, end);
    }
    var sortedIndex = createSortedIndex();
    var sortedLastIndex = createSortedIndex(true);
    function take(array, n, guard) {
      var length = array ? array.length : 0;
      if (!length) {
        return [];
      }
      if (guard ? isIterateeCall(array, n, guard) : n == null) {
        n = 1;
      }
      return baseSlice(array, 0, n < 0 ? 0 : n);
    }
    function takeRight(array, n, guard) {
      var length = array ? array.length : 0;
      if (!length) {
        return [];
      }
      if (guard ? isIterateeCall(array, n, guard) : n == null) {
        n = 1;
      }
      n = length - (+n || 0);
      return baseSlice(array, n < 0 ? 0 : n);
    }
    function takeRightWhile(array, predicate, thisArg) {
      return (array && array.length) ? baseWhile(array, getCallback(predicate, thisArg, 3), false, true) : [];
    }
    function takeWhile(array, predicate, thisArg) {
      return (array && array.length) ? baseWhile(array, getCallback(predicate, thisArg, 3)) : [];
    }
    var union = restParam(function(arrays) {
      return baseUniq(baseFlatten(arrays, false, true));
    });
    function uniq(array, isSorted, iteratee, thisArg) {
      var length = array ? array.length : 0;
      if (!length) {
        return [];
      }
      if (isSorted != null && typeof isSorted != 'boolean') {
        thisArg = iteratee;
        iteratee = isIterateeCall(array, isSorted, thisArg) ? undefined : isSorted;
        isSorted = false;
      }
      var callback = getCallback();
      if (!(iteratee == null && callback === baseCallback)) {
        iteratee = callback(iteratee, thisArg, 3);
      }
      return (isSorted && getIndexOf() == baseIndexOf) ? sortedUniq(array, iteratee) : baseUniq(array, iteratee);
    }
    function unzip(array) {
      if (!(array && array.length)) {
        return [];
      }
      var index = -1,
          length = 0;
      array = arrayFilter(array, function(group) {
        if (isArrayLike(group)) {
          length = nativeMax(group.length, length);
          return true;
        }
      });
      var result = Array(length);
      while (++index < length) {
        result[index] = arrayMap(array, baseProperty(index));
      }
      return result;
    }
    function unzipWith(array, iteratee, thisArg) {
      var length = array ? array.length : 0;
      if (!length) {
        return [];
      }
      var result = unzip(array);
      if (iteratee == null) {
        return result;
      }
      iteratee = bindCallback(iteratee, thisArg, 4);
      return arrayMap(result, function(group) {
        return arrayReduce(group, iteratee, undefined, true);
      });
    }
    var without = restParam(function(array, values) {
      return isArrayLike(array) ? baseDifference(array, values) : [];
    });
    function xor() {
      var index = -1,
          length = arguments.length;
      while (++index < length) {
        var array = arguments[index];
        if (isArrayLike(array)) {
          var result = result ? arrayPush(baseDifference(result, array), baseDifference(array, result)) : array;
        }
      }
      return result ? baseUniq(result) : [];
    }
    var zip = restParam(unzip);
    function zipObject(props, values) {
      var index = -1,
          length = props ? props.length : 0,
          result = {};
      if (length && !values && !isArray(props[0])) {
        values = [];
      }
      while (++index < length) {
        var key = props[index];
        if (values) {
          result[key] = values[index];
        } else if (key) {
          result[key[0]] = key[1];
        }
      }
      return result;
    }
    var zipWith = restParam(function(arrays) {
      var length = arrays.length,
          iteratee = length > 2 ? arrays[length - 2] : undefined,
          thisArg = length > 1 ? arrays[length - 1] : undefined;
      if (length > 2 && typeof iteratee == 'function') {
        length -= 2;
      } else {
        iteratee = (length > 1 && typeof thisArg == 'function') ? (--length, thisArg) : undefined;
        thisArg = undefined;
      }
      arrays.length = length;
      return unzipWith(arrays, iteratee, thisArg);
    });
    function chain(value) {
      var result = lodash(value);
      result.__chain__ = true;
      return result;
    }
    function tap(value, interceptor, thisArg) {
      interceptor.call(thisArg, value);
      return value;
    }
    function thru(value, interceptor, thisArg) {
      return interceptor.call(thisArg, value);
    }
    function wrapperChain() {
      return chain(this);
    }
    function wrapperCommit() {
      return new LodashWrapper(this.value(), this.__chain__);
    }
    var wrapperConcat = restParam(function(values) {
      values = baseFlatten(values);
      return this.thru(function(array) {
        return arrayConcat(isArray(array) ? array : [toObject(array)], values);
      });
    });
    function wrapperPlant(value) {
      var result,
          parent = this;
      while (parent instanceof baseLodash) {
        var clone = wrapperClone(parent);
        if (result) {
          previous.__wrapped__ = clone;
        } else {
          result = clone;
        }
        var previous = clone;
        parent = parent.__wrapped__;
      }
      previous.__wrapped__ = value;
      return result;
    }
    function wrapperReverse() {
      var value = this.__wrapped__;
      var interceptor = function(value) {
        return (wrapped && wrapped.__dir__ < 0) ? value : value.reverse();
      };
      if (value instanceof LazyWrapper) {
        var wrapped = value;
        if (this.__actions__.length) {
          wrapped = new LazyWrapper(this);
        }
        wrapped = wrapped.reverse();
        wrapped.__actions__.push({
          'func': thru,
          'args': [interceptor],
          'thisArg': undefined
        });
        return new LodashWrapper(wrapped, this.__chain__);
      }
      return this.thru(interceptor);
    }
    function wrapperToString() {
      return (this.value() + '');
    }
    function wrapperValue() {
      return baseWrapperValue(this.__wrapped__, this.__actions__);
    }
    var at = restParam(function(collection, props) {
      return baseAt(collection, baseFlatten(props));
    });
    var countBy = createAggregator(function(result, value, key) {
      hasOwnProperty.call(result, key) ? ++result[key] : (result[key] = 1);
    });
    function every(collection, predicate, thisArg) {
      var func = isArray(collection) ? arrayEvery : baseEvery;
      if (thisArg && isIterateeCall(collection, predicate, thisArg)) {
        predicate = undefined;
      }
      if (typeof predicate != 'function' || thisArg !== undefined) {
        predicate = getCallback(predicate, thisArg, 3);
      }
      return func(collection, predicate);
    }
    function filter(collection, predicate, thisArg) {
      var func = isArray(collection) ? arrayFilter : baseFilter;
      predicate = getCallback(predicate, thisArg, 3);
      return func(collection, predicate);
    }
    var find = createFind(baseEach);
    var findLast = createFind(baseEachRight, true);
    function findWhere(collection, source) {
      return find(collection, baseMatches(source));
    }
    var forEach = createForEach(arrayEach, baseEach);
    var forEachRight = createForEach(arrayEachRight, baseEachRight);
    var groupBy = createAggregator(function(result, value, key) {
      if (hasOwnProperty.call(result, key)) {
        result[key].push(value);
      } else {
        result[key] = [value];
      }
    });
    function includes(collection, target, fromIndex, guard) {
      var length = collection ? getLength(collection) : 0;
      if (!isLength(length)) {
        collection = values(collection);
        length = collection.length;
      }
      if (typeof fromIndex != 'number' || (guard && isIterateeCall(target, fromIndex, guard))) {
        fromIndex = 0;
      } else {
        fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : (fromIndex || 0);
      }
      return (typeof collection == 'string' || !isArray(collection) && isString(collection)) ? (fromIndex <= length && collection.indexOf(target, fromIndex) > -1) : (!!length && getIndexOf(collection, target, fromIndex) > -1);
    }
    var indexBy = createAggregator(function(result, value, key) {
      result[key] = value;
    });
    var invoke = restParam(function(collection, path, args) {
      var index = -1,
          isFunc = typeof path == 'function',
          isProp = isKey(path),
          result = isArrayLike(collection) ? Array(collection.length) : [];
      baseEach(collection, function(value) {
        var func = isFunc ? path : ((isProp && value != null) ? value[path] : undefined);
        result[++index] = func ? func.apply(value, args) : invokePath(value, path, args);
      });
      return result;
    });
    function map(collection, iteratee, thisArg) {
      var func = isArray(collection) ? arrayMap : baseMap;
      iteratee = getCallback(iteratee, thisArg, 3);
      return func(collection, iteratee);
    }
    var partition = createAggregator(function(result, value, key) {
      result[key ? 0 : 1].push(value);
    }, function() {
      return [[], []];
    });
    function pluck(collection, path) {
      return map(collection, property(path));
    }
    var reduce = createReduce(arrayReduce, baseEach);
    var reduceRight = createReduce(arrayReduceRight, baseEachRight);
    function reject(collection, predicate, thisArg) {
      var func = isArray(collection) ? arrayFilter : baseFilter;
      predicate = getCallback(predicate, thisArg, 3);
      return func(collection, function(value, index, collection) {
        return !predicate(value, index, collection);
      });
    }
    function sample(collection, n, guard) {
      if (guard ? isIterateeCall(collection, n, guard) : n == null) {
        collection = toIterable(collection);
        var length = collection.length;
        return length > 0 ? collection[baseRandom(0, length - 1)] : undefined;
      }
      var index = -1,
          result = toArray(collection),
          length = result.length,
          lastIndex = length - 1;
      n = nativeMin(n < 0 ? 0 : (+n || 0), length);
      while (++index < n) {
        var rand = baseRandom(index, lastIndex),
            value = result[rand];
        result[rand] = result[index];
        result[index] = value;
      }
      result.length = n;
      return result;
    }
    function shuffle(collection) {
      return sample(collection, POSITIVE_INFINITY);
    }
    function size(collection) {
      var length = collection ? getLength(collection) : 0;
      return isLength(length) ? length : keys(collection).length;
    }
    function some(collection, predicate, thisArg) {
      var func = isArray(collection) ? arraySome : baseSome;
      if (thisArg && isIterateeCall(collection, predicate, thisArg)) {
        predicate = undefined;
      }
      if (typeof predicate != 'function' || thisArg !== undefined) {
        predicate = getCallback(predicate, thisArg, 3);
      }
      return func(collection, predicate);
    }
    function sortBy(collection, iteratee, thisArg) {
      if (collection == null) {
        return [];
      }
      if (thisArg && isIterateeCall(collection, iteratee, thisArg)) {
        iteratee = undefined;
      }
      var index = -1;
      iteratee = getCallback(iteratee, thisArg, 3);
      var result = baseMap(collection, function(value, key, collection) {
        return {
          'criteria': iteratee(value, key, collection),
          'index': ++index,
          'value': value
        };
      });
      return baseSortBy(result, compareAscending);
    }
    var sortByAll = restParam(function(collection, iteratees) {
      if (collection == null) {
        return [];
      }
      var guard = iteratees[2];
      if (guard && isIterateeCall(iteratees[0], iteratees[1], guard)) {
        iteratees.length = 1;
      }
      return baseSortByOrder(collection, baseFlatten(iteratees), []);
    });
    function sortByOrder(collection, iteratees, orders, guard) {
      if (collection == null) {
        return [];
      }
      if (guard && isIterateeCall(iteratees, orders, guard)) {
        orders = undefined;
      }
      if (!isArray(iteratees)) {
        iteratees = iteratees == null ? [] : [iteratees];
      }
      if (!isArray(orders)) {
        orders = orders == null ? [] : [orders];
      }
      return baseSortByOrder(collection, iteratees, orders);
    }
    function where(collection, source) {
      return filter(collection, baseMatches(source));
    }
    var now = nativeNow || function() {
      return new Date().getTime();
    };
    function after(n, func) {
      if (typeof func != 'function') {
        if (typeof n == 'function') {
          var temp = n;
          n = func;
          func = temp;
        } else {
          throw new TypeError(FUNC_ERROR_TEXT);
        }
      }
      n = nativeIsFinite(n = +n) ? n : 0;
      return function() {
        if (--n < 1) {
          return func.apply(this, arguments);
        }
      };
    }
    function ary(func, n, guard) {
      if (guard && isIterateeCall(func, n, guard)) {
        n = undefined;
      }
      n = (func && n == null) ? func.length : nativeMax(+n || 0, 0);
      return createWrapper(func, ARY_FLAG, undefined, undefined, undefined, undefined, n);
    }
    function before(n, func) {
      var result;
      if (typeof func != 'function') {
        if (typeof n == 'function') {
          var temp = n;
          n = func;
          func = temp;
        } else {
          throw new TypeError(FUNC_ERROR_TEXT);
        }
      }
      return function() {
        if (--n > 0) {
          result = func.apply(this, arguments);
        }
        if (n <= 1) {
          func = undefined;
        }
        return result;
      };
    }
    var bind = restParam(function(func, thisArg, partials) {
      var bitmask = BIND_FLAG;
      if (partials.length) {
        var holders = replaceHolders(partials, bind.placeholder);
        bitmask |= PARTIAL_FLAG;
      }
      return createWrapper(func, bitmask, thisArg, partials, holders);
    });
    var bindAll = restParam(function(object, methodNames) {
      methodNames = methodNames.length ? baseFlatten(methodNames) : functions(object);
      var index = -1,
          length = methodNames.length;
      while (++index < length) {
        var key = methodNames[index];
        object[key] = createWrapper(object[key], BIND_FLAG, object);
      }
      return object;
    });
    var bindKey = restParam(function(object, key, partials) {
      var bitmask = BIND_FLAG | BIND_KEY_FLAG;
      if (partials.length) {
        var holders = replaceHolders(partials, bindKey.placeholder);
        bitmask |= PARTIAL_FLAG;
      }
      return createWrapper(key, bitmask, object, partials, holders);
    });
    var curry = createCurry(CURRY_FLAG);
    var curryRight = createCurry(CURRY_RIGHT_FLAG);
    function debounce(func, wait, options) {
      var args,
          maxTimeoutId,
          result,
          stamp,
          thisArg,
          timeoutId,
          trailingCall,
          lastCalled = 0,
          maxWait = false,
          trailing = true;
      if (typeof func != 'function') {
        throw new TypeError(FUNC_ERROR_TEXT);
      }
      wait = wait < 0 ? 0 : (+wait || 0);
      if (options === true) {
        var leading = true;
        trailing = false;
      } else if (isObject(options)) {
        leading = !!options.leading;
        maxWait = 'maxWait' in options && nativeMax(+options.maxWait || 0, wait);
        trailing = 'trailing' in options ? !!options.trailing : trailing;
      }
      function cancel() {
        if (timeoutId) {
          clearTimeout(timeoutId);
        }
        if (maxTimeoutId) {
          clearTimeout(maxTimeoutId);
        }
        lastCalled = 0;
        maxTimeoutId = timeoutId = trailingCall = undefined;
      }
      function complete(isCalled, id) {
        if (id) {
          clearTimeout(id);
        }
        maxTimeoutId = timeoutId = trailingCall = undefined;
        if (isCalled) {
          lastCalled = now();
          result = func.apply(thisArg, args);
          if (!timeoutId && !maxTimeoutId) {
            args = thisArg = undefined;
          }
        }
      }
      function delayed() {
        var remaining = wait - (now() - stamp);
        if (remaining <= 0 || remaining > wait) {
          complete(trailingCall, maxTimeoutId);
        } else {
          timeoutId = setTimeout(delayed, remaining);
        }
      }
      function maxDelayed() {
        complete(trailing, timeoutId);
      }
      function debounced() {
        args = arguments;
        stamp = now();
        thisArg = this;
        trailingCall = trailing && (timeoutId || !leading);
        if (maxWait === false) {
          var leadingCall = leading && !timeoutId;
        } else {
          if (!maxTimeoutId && !leading) {
            lastCalled = stamp;
          }
          var remaining = maxWait - (stamp - lastCalled),
              isCalled = remaining <= 0 || remaining > maxWait;
          if (isCalled) {
            if (maxTimeoutId) {
              maxTimeoutId = clearTimeout(maxTimeoutId);
            }
            lastCalled = stamp;
            result = func.apply(thisArg, args);
          } else if (!maxTimeoutId) {
            maxTimeoutId = setTimeout(maxDelayed, remaining);
          }
        }
        if (isCalled && timeoutId) {
          timeoutId = clearTimeout(timeoutId);
        } else if (!timeoutId && wait !== maxWait) {
          timeoutId = setTimeout(delayed, wait);
        }
        if (leadingCall) {
          isCalled = true;
          result = func.apply(thisArg, args);
        }
        if (isCalled && !timeoutId && !maxTimeoutId) {
          args = thisArg = undefined;
        }
        return result;
      }
      debounced.cancel = cancel;
      return debounced;
    }
    var defer = restParam(function(func, args) {
      return baseDelay(func, 1, args);
    });
    var delay = restParam(function(func, wait, args) {
      return baseDelay(func, wait, args);
    });
    var flow = createFlow();
    var flowRight = createFlow(true);
    function memoize(func, resolver) {
      if (typeof func != 'function' || (resolver && typeof resolver != 'function')) {
        throw new TypeError(FUNC_ERROR_TEXT);
      }
      var memoized = function() {
        var args = arguments,
            key = resolver ? resolver.apply(this, args) : args[0],
            cache = memoized.cache;
        if (cache.has(key)) {
          return cache.get(key);
        }
        var result = func.apply(this, args);
        memoized.cache = cache.set(key, result);
        return result;
      };
      memoized.cache = new memoize.Cache;
      return memoized;
    }
    var modArgs = restParam(function(func, transforms) {
      transforms = baseFlatten(transforms);
      if (typeof func != 'function' || !arrayEvery(transforms, baseIsFunction)) {
        throw new TypeError(FUNC_ERROR_TEXT);
      }
      var length = transforms.length;
      return restParam(function(args) {
        var index = nativeMin(args.length, length);
        while (index--) {
          args[index] = transforms[index](args[index]);
        }
        return func.apply(this, args);
      });
    });
    function negate(predicate) {
      if (typeof predicate != 'function') {
        throw new TypeError(FUNC_ERROR_TEXT);
      }
      return function() {
        return !predicate.apply(this, arguments);
      };
    }
    function once(func) {
      return before(2, func);
    }
    var partial = createPartial(PARTIAL_FLAG);
    var partialRight = createPartial(PARTIAL_RIGHT_FLAG);
    var rearg = restParam(function(func, indexes) {
      return createWrapper(func, REARG_FLAG, undefined, undefined, undefined, baseFlatten(indexes));
    });
    function restParam(func, start) {
      if (typeof func != 'function') {
        throw new TypeError(FUNC_ERROR_TEXT);
      }
      start = nativeMax(start === undefined ? (func.length - 1) : (+start || 0), 0);
      return function() {
        var args = arguments,
            index = -1,
            length = nativeMax(args.length - start, 0),
            rest = Array(length);
        while (++index < length) {
          rest[index] = args[start + index];
        }
        switch (start) {
          case 0:
            return func.call(this, rest);
          case 1:
            return func.call(this, args[0], rest);
          case 2:
            return func.call(this, args[0], args[1], rest);
        }
        var otherArgs = Array(start + 1);
        index = -1;
        while (++index < start) {
          otherArgs[index] = args[index];
        }
        otherArgs[start] = rest;
        return func.apply(this, otherArgs);
      };
    }
    function spread(func) {
      if (typeof func != 'function') {
        throw new TypeError(FUNC_ERROR_TEXT);
      }
      return function(array) {
        return func.apply(this, array);
      };
    }
    function throttle(func, wait, options) {
      var leading = true,
          trailing = true;
      if (typeof func != 'function') {
        throw new TypeError(FUNC_ERROR_TEXT);
      }
      if (options === false) {
        leading = false;
      } else if (isObject(options)) {
        leading = 'leading' in options ? !!options.leading : leading;
        trailing = 'trailing' in options ? !!options.trailing : trailing;
      }
      return debounce(func, wait, {
        'leading': leading,
        'maxWait': +wait,
        'trailing': trailing
      });
    }
    function wrap(value, wrapper) {
      wrapper = wrapper == null ? identity : wrapper;
      return createWrapper(wrapper, PARTIAL_FLAG, undefined, [value], []);
    }
    function clone(value, isDeep, customizer, thisArg) {
      if (isDeep && typeof isDeep != 'boolean' && isIterateeCall(value, isDeep, customizer)) {
        isDeep = false;
      } else if (typeof isDeep == 'function') {
        thisArg = customizer;
        customizer = isDeep;
        isDeep = false;
      }
      return typeof customizer == 'function' ? baseClone(value, isDeep, bindCallback(customizer, thisArg, 1)) : baseClone(value, isDeep);
    }
    function cloneDeep(value, customizer, thisArg) {
      return typeof customizer == 'function' ? baseClone(value, true, bindCallback(customizer, thisArg, 1)) : baseClone(value, true);
    }
    function gt(value, other) {
      return value > other;
    }
    function gte(value, other) {
      return value >= other;
    }
    function isArguments(value) {
      return isObjectLike(value) && isArrayLike(value) && hasOwnProperty.call(value, 'callee') && !propertyIsEnumerable.call(value, 'callee');
    }
    var isArray = nativeIsArray || function(value) {
      return isObjectLike(value) && isLength(value.length) && objToString.call(value) == arrayTag;
    };
    function isBoolean(value) {
      return value === true || value === false || (isObjectLike(value) && objToString.call(value) == boolTag);
    }
    function isDate(value) {
      return isObjectLike(value) && objToString.call(value) == dateTag;
    }
    function isElement(value) {
      return !!value && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value);
    }
    function isEmpty(value) {
      if (value == null) {
        return true;
      }
      if (isArrayLike(value) && (isArray(value) || isString(value) || isArguments(value) || (isObjectLike(value) && isFunction(value.splice)))) {
        return !value.length;
      }
      return !keys(value).length;
    }
    function isEqual(value, other, customizer, thisArg) {
      customizer = typeof customizer == 'function' ? bindCallback(customizer, thisArg, 3) : undefined;
      var result = customizer ? customizer(value, other) : undefined;
      return result === undefined ? baseIsEqual(value, other, customizer) : !!result;
    }
    function isError(value) {
      return isObjectLike(value) && typeof value.message == 'string' && objToString.call(value) == errorTag;
    }
    function isFinite(value) {
      return typeof value == 'number' && nativeIsFinite(value);
    }
    function isFunction(value) {
      return isObject(value) && objToString.call(value) == funcTag;
    }
    function isObject(value) {
      var type = typeof value;
      return !!value && (type == 'object' || type == 'function');
    }
    function isMatch(object, source, customizer, thisArg) {
      customizer = typeof customizer == 'function' ? bindCallback(customizer, thisArg, 3) : undefined;
      return baseIsMatch(object, getMatchData(source), customizer);
    }
    function isNaN(value) {
      return isNumber(value) && value != +value;
    }
    function isNative(value) {
      if (value == null) {
        return false;
      }
      if (isFunction(value)) {
        return reIsNative.test(fnToString.call(value));
      }
      return isObjectLike(value) && reIsHostCtor.test(value);
    }
    function isNull(value) {
      return value === null;
    }
    function isNumber(value) {
      return typeof value == 'number' || (isObjectLike(value) && objToString.call(value) == numberTag);
    }
    function isPlainObject(value) {
      var Ctor;
      if (!(isObjectLike(value) && objToString.call(value) == objectTag && !isArguments(value)) || (!hasOwnProperty.call(value, 'constructor') && (Ctor = value.constructor, typeof Ctor == 'function' && !(Ctor instanceof Ctor)))) {
        return false;
      }
      var result;
      baseForIn(value, function(subValue, key) {
        result = key;
      });
      return result === undefined || hasOwnProperty.call(value, result);
    }
    function isRegExp(value) {
      return isObject(value) && objToString.call(value) == regexpTag;
    }
    function isString(value) {
      return typeof value == 'string' || (isObjectLike(value) && objToString.call(value) == stringTag);
    }
    function isTypedArray(value) {
      return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[objToString.call(value)];
    }
    function isUndefined(value) {
      return value === undefined;
    }
    function lt(value, other) {
      return value < other;
    }
    function lte(value, other) {
      return value <= other;
    }
    function toArray(value) {
      var length = value ? getLength(value) : 0;
      if (!isLength(length)) {
        return values(value);
      }
      if (!length) {
        return [];
      }
      return arrayCopy(value);
    }
    function toPlainObject(value) {
      return baseCopy(value, keysIn(value));
    }
    var merge = createAssigner(baseMerge);
    var assign = createAssigner(function(object, source, customizer) {
      return customizer ? assignWith(object, source, customizer) : baseAssign(object, source);
    });
    function create(prototype, properties, guard) {
      var result = baseCreate(prototype);
      if (guard && isIterateeCall(prototype, properties, guard)) {
        properties = undefined;
      }
      return properties ? baseAssign(result, properties) : result;
    }
    var defaults = createDefaults(assign, assignDefaults);
    var defaultsDeep = createDefaults(merge, mergeDefaults);
    var findKey = createFindKey(baseForOwn);
    var findLastKey = createFindKey(baseForOwnRight);
    var forIn = createForIn(baseFor);
    var forInRight = createForIn(baseForRight);
    var forOwn = createForOwn(baseForOwn);
    var forOwnRight = createForOwn(baseForOwnRight);
    function functions(object) {
      return baseFunctions(object, keysIn(object));
    }
    function get(object, path, defaultValue) {
      var result = object == null ? undefined : baseGet(object, toPath(path), path + '');
      return result === undefined ? defaultValue : result;
    }
    function has(object, path) {
      if (object == null) {
        return false;
      }
      var result = hasOwnProperty.call(object, path);
      if (!result && !isKey(path)) {
        path = toPath(path);
        object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1));
        if (object == null) {
          return false;
        }
        path = last(path);
        result = hasOwnProperty.call(object, path);
      }
      return result || (isLength(object.length) && isIndex(path, object.length) && (isArray(object) || isArguments(object)));
    }
    function invert(object, multiValue, guard) {
      if (guard && isIterateeCall(object, multiValue, guard)) {
        multiValue = undefined;
      }
      var index = -1,
          props = keys(object),
          length = props.length,
          result = {};
      while (++index < length) {
        var key = props[index],
            value = object[key];
        if (multiValue) {
          if (hasOwnProperty.call(result, value)) {
            result[value].push(key);
          } else {
            result[value] = [key];
          }
        } else {
          result[value] = key;
        }
      }
      return result;
    }
    var keys = !nativeKeys ? shimKeys : function(object) {
      var Ctor = object == null ? undefined : object.constructor;
      if ((typeof Ctor == 'function' && Ctor.prototype === object) || (typeof object != 'function' && isArrayLike(object))) {
        return shimKeys(object);
      }
      return isObject(object) ? nativeKeys(object) : [];
    };
    function keysIn(object) {
      if (object == null) {
        return [];
      }
      if (!isObject(object)) {
        object = Object(object);
      }
      var length = object.length;
      length = (length && isLength(length) && (isArray(object) || isArguments(object)) && length) || 0;
      var Ctor = object.constructor,
          index = -1,
          isProto = typeof Ctor == 'function' && Ctor.prototype === object,
          result = Array(length),
          skipIndexes = length > 0;
      while (++index < length) {
        result[index] = (index + '');
      }
      for (var key in object) {
        if (!(skipIndexes && isIndex(key, length)) && !(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {
          result.push(key);
        }
      }
      return result;
    }
    var mapKeys = createObjectMapper(true);
    var mapValues = createObjectMapper();
    var omit = restParam(function(object, props) {
      if (object == null) {
        return {};
      }
      if (typeof props[0] != 'function') {
        var props = arrayMap(baseFlatten(props), String);
        return pickByArray(object, baseDifference(keysIn(object), props));
      }
      var predicate = bindCallback(props[0], props[1], 3);
      return pickByCallback(object, function(value, key, object) {
        return !predicate(value, key, object);
      });
    });
    function pairs(object) {
      object = toObject(object);
      var index = -1,
          props = keys(object),
          length = props.length,
          result = Array(length);
      while (++index < length) {
        var key = props[index];
        result[index] = [key, object[key]];
      }
      return result;
    }
    var pick = restParam(function(object, props) {
      if (object == null) {
        return {};
      }
      return typeof props[0] == 'function' ? pickByCallback(object, bindCallback(props[0], props[1], 3)) : pickByArray(object, baseFlatten(props));
    });
    function result(object, path, defaultValue) {
      var result = object == null ? undefined : object[path];
      if (result === undefined) {
        if (object != null && !isKey(path, object)) {
          path = toPath(path);
          object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1));
          result = object == null ? undefined : object[last(path)];
        }
        result = result === undefined ? defaultValue : result;
      }
      return isFunction(result) ? result.call(object) : result;
    }
    function set(object, path, value) {
      if (object == null) {
        return object;
      }
      var pathKey = (path + '');
      path = (object[pathKey] != null || isKey(path, object)) ? [pathKey] : toPath(path);
      var index = -1,
          length = path.length,
          lastIndex = length - 1,
          nested = object;
      while (nested != null && ++index < length) {
        var key = path[index];
        if (isObject(nested)) {
          if (index == lastIndex) {
            nested[key] = value;
          } else if (nested[key] == null) {
            nested[key] = isIndex(path[index + 1]) ? [] : {};
          }
        }
        nested = nested[key];
      }
      return object;
    }
    function transform(object, iteratee, accumulator, thisArg) {
      var isArr = isArray(object) || isTypedArray(object);
      iteratee = getCallback(iteratee, thisArg, 4);
      if (accumulator == null) {
        if (isArr || isObject(object)) {
          var Ctor = object.constructor;
          if (isArr) {
            accumulator = isArray(object) ? new Ctor : [];
          } else {
            accumulator = baseCreate(isFunction(Ctor) ? Ctor.prototype : undefined);
          }
        } else {
          accumulator = {};
        }
      }
      (isArr ? arrayEach : baseForOwn)(object, function(value, index, object) {
        return iteratee(accumulator, value, index, object);
      });
      return accumulator;
    }
    function values(object) {
      return baseValues(object, keys(object));
    }
    function valuesIn(object) {
      return baseValues(object, keysIn(object));
    }
    function inRange(value, start, end) {
      start = +start || 0;
      if (end === undefined) {
        end = start;
        start = 0;
      } else {
        end = +end || 0;
      }
      return value >= nativeMin(start, end) && value < nativeMax(start, end);
    }
    function random(min, max, floating) {
      if (floating && isIterateeCall(min, max, floating)) {
        max = floating = undefined;
      }
      var noMin = min == null,
          noMax = max == null;
      if (floating == null) {
        if (noMax && typeof min == 'boolean') {
          floating = min;
          min = 1;
        } else if (typeof max == 'boolean') {
          floating = max;
          noMax = true;
        }
      }
      if (noMin && noMax) {
        max = 1;
        noMax = false;
      }
      min = +min || 0;
      if (noMax) {
        max = min;
        min = 0;
      } else {
        max = +max || 0;
      }
      if (floating || min % 1 || max % 1) {
        var rand = nativeRandom();
        return nativeMin(min + (rand * (max - min + parseFloat('1e-' + ((rand + '').length - 1)))), max);
      }
      return baseRandom(min, max);
    }
    var camelCase = createCompounder(function(result, word, index) {
      word = word.toLowerCase();
      return result + (index ? (word.charAt(0).toUpperCase() + word.slice(1)) : word);
    });
    function capitalize(string) {
      string = baseToString(string);
      return string && (string.charAt(0).toUpperCase() + string.slice(1));
    }
    function deburr(string) {
      string = baseToString(string);
      return string && string.replace(reLatin1, deburrLetter).replace(reComboMark, '');
    }
    function endsWith(string, target, position) {
      string = baseToString(string);
      target = (target + '');
      var length = string.length;
      position = position === undefined ? length : nativeMin(position < 0 ? 0 : (+position || 0), length);
      position -= target.length;
      return position >= 0 && string.indexOf(target, position) == position;
    }
    function escape(string) {
      string = baseToString(string);
      return (string && reHasUnescapedHtml.test(string)) ? string.replace(reUnescapedHtml, escapeHtmlChar) : string;
    }
    function escapeRegExp(string) {
      string = baseToString(string);
      return (string && reHasRegExpChars.test(string)) ? string.replace(reRegExpChars, escapeRegExpChar) : (string || '(?:)');
    }
    var kebabCase = createCompounder(function(result, word, index) {
      return result + (index ? '-' : '') + word.toLowerCase();
    });
    function pad(string, length, chars) {
      string = baseToString(string);
      length = +length;
      var strLength = string.length;
      if (strLength >= length || !nativeIsFinite(length)) {
        return string;
      }
      var mid = (length - strLength) / 2,
          leftLength = nativeFloor(mid),
          rightLength = nativeCeil(mid);
      chars = createPadding('', rightLength, chars);
      return chars.slice(0, leftLength) + string + chars;
    }
    var padLeft = createPadDir();
    var padRight = createPadDir(true);
    function parseInt(string, radix, guard) {
      if (guard ? isIterateeCall(string, radix, guard) : radix == null) {
        radix = 0;
      } else if (radix) {
        radix = +radix;
      }
      string = trim(string);
      return nativeParseInt(string, radix || (reHasHexPrefix.test(string) ? 16 : 10));
    }
    function repeat(string, n) {
      var result = '';
      string = baseToString(string);
      n = +n;
      if (n < 1 || !string || !nativeIsFinite(n)) {
        return result;
      }
      do {
        if (n % 2) {
          result += string;
        }
        n = nativeFloor(n / 2);
        string += string;
      } while (n);
      return result;
    }
    var snakeCase = createCompounder(function(result, word, index) {
      return result + (index ? '_' : '') + word.toLowerCase();
    });
    var startCase = createCompounder(function(result, word, index) {
      return result + (index ? ' ' : '') + (word.charAt(0).toUpperCase() + word.slice(1));
    });
    function startsWith(string, target, position) {
      string = baseToString(string);
      position = position == null ? 0 : nativeMin(position < 0 ? 0 : (+position || 0), string.length);
      return string.lastIndexOf(target, position) == position;
    }
    function template(string, options, otherOptions) {
      var settings = lodash.templateSettings;
      if (otherOptions && isIterateeCall(string, options, otherOptions)) {
        options = otherOptions = undefined;
      }
      string = baseToString(string);
      options = assignWith(baseAssign({}, otherOptions || options), settings, assignOwnDefaults);
      var imports = assignWith(baseAssign({}, options.imports), settings.imports, assignOwnDefaults),
          importsKeys = keys(imports),
          importsValues = baseValues(imports, importsKeys);
      var isEscaping,
          isEvaluating,
          index = 0,
          interpolate = options.interpolate || reNoMatch,
          source = "__p += '";
      var reDelimiters = RegExp((options.escape || reNoMatch).source + '|' + interpolate.source + '|' + (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' + (options.evaluate || reNoMatch).source + '|$', 'g');
      var sourceURL = '//# sourceURL=' + ('sourceURL' in options ? options.sourceURL : ('lodash.templateSources[' + (++templateCounter) + ']')) + '\n';
      string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
        interpolateValue || (interpolateValue = esTemplateValue);
        source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar);
        if (escapeValue) {
          isEscaping = true;
          source += "' +\n__e(" + escapeValue + ") +\n'";
        }
        if (evaluateValue) {
          isEvaluating = true;
          source += "';\n" + evaluateValue + ";\n__p += '";
        }
        if (interpolateValue) {
          source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
        }
        index = offset + match.length;
        return match;
      });
      source += "';\n";
      var variable = options.variable;
      if (!variable) {
        source = 'with (obj) {\n' + source + '\n}\n';
      }
      source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source).replace(reEmptyStringMiddle, '$1').replace(reEmptyStringTrailing, '$1;');
      source = 'function(' + (variable || 'obj') + ') {\n' + (variable ? '' : 'obj || (obj = {});\n') + "var __t, __p = ''" + (isEscaping ? ', __e = _.escape' : '') + (isEvaluating ? ', __j = Array.prototype.join;\n' + "function print() { __p += __j.call(arguments, '') }\n" : ';\n') + source + 'return __p\n}';
      var result = attempt(function() {
        return Function(importsKeys, sourceURL + 'return ' + source).apply(undefined, importsValues);
      });
      result.source = source;
      if (isError(result)) {
        throw result;
      }
      return result;
    }
    function trim(string, chars, guard) {
      var value = string;
      string = baseToString(string);
      if (!string) {
        return string;
      }
      if (guard ? isIterateeCall(value, chars, guard) : chars == null) {
        return string.slice(trimmedLeftIndex(string), trimmedRightIndex(string) + 1);
      }
      chars = (chars + '');
      return string.slice(charsLeftIndex(string, chars), charsRightIndex(string, chars) + 1);
    }
    function trimLeft(string, chars, guard) {
      var value = string;
      string = baseToString(string);
      if (!string) {
        return string;
      }
      if (guard ? isIterateeCall(value, chars, guard) : chars == null) {
        return string.slice(trimmedLeftIndex(string));
      }
      return string.slice(charsLeftIndex(string, (chars + '')));
    }
    function trimRight(string, chars, guard) {
      var value = string;
      string = baseToString(string);
      if (!string) {
        return string;
      }
      if (guard ? isIterateeCall(value, chars, guard) : chars == null) {
        return string.slice(0, trimmedRightIndex(string) + 1);
      }
      return string.slice(0, charsRightIndex(string, (chars + '')) + 1);
    }
    function trunc(string, options, guard) {
      if (guard && isIterateeCall(string, options, guard)) {
        options = undefined;
      }
      var length = DEFAULT_TRUNC_LENGTH,
          omission = DEFAULT_TRUNC_OMISSION;
      if (options != null) {
        if (isObject(options)) {
          var separator = 'separator' in options ? options.separator : separator;
          length = 'length' in options ? (+options.length || 0) : length;
          omission = 'omission' in options ? baseToString(options.omission) : omission;
        } else {
          length = +options || 0;
        }
      }
      string = baseToString(string);
      if (length >= string.length) {
        return string;
      }
      var end = length - omission.length;
      if (end < 1) {
        return omission;
      }
      var result = string.slice(0, end);
      if (separator == null) {
        return result + omission;
      }
      if (isRegExp(separator)) {
        if (string.slice(end).search(separator)) {
          var match,
              newEnd,
              substring = string.slice(0, end);
          if (!separator.global) {
            separator = RegExp(separator.source, (reFlags.exec(separator) || '') + 'g');
          }
          separator.lastIndex = 0;
          while ((match = separator.exec(substring))) {
            newEnd = match.index;
          }
          result = result.slice(0, newEnd == null ? end : newEnd);
        }
      } else if (string.indexOf(separator, end) != end) {
        var index = result.lastIndexOf(separator);
        if (index > -1) {
          result = result.slice(0, index);
        }
      }
      return result + omission;
    }
    function unescape(string) {
      string = baseToString(string);
      return (string && reHasEscapedHtml.test(string)) ? string.replace(reEscapedHtml, unescapeHtmlChar) : string;
    }
    function words(string, pattern, guard) {
      if (guard && isIterateeCall(string, pattern, guard)) {
        pattern = undefined;
      }
      string = baseToString(string);
      return string.match(pattern || reWords) || [];
    }
    var attempt = restParam(function(func, args) {
      try {
        return func.apply(undefined, args);
      } catch (e) {
        return isError(e) ? e : new Error(e);
      }
    });
    function callback(func, thisArg, guard) {
      if (guard && isIterateeCall(func, thisArg, guard)) {
        thisArg = undefined;
      }
      return isObjectLike(func) ? matches(func) : baseCallback(func, thisArg);
    }
    function constant(value) {
      return function() {
        return value;
      };
    }
    function identity(value) {
      return value;
    }
    function matches(source) {
      return baseMatches(baseClone(source, true));
    }
    function matchesProperty(path, srcValue) {
      return baseMatchesProperty(path, baseClone(srcValue, true));
    }
    var method = restParam(function(path, args) {
      return function(object) {
        return invokePath(object, path, args);
      };
    });
    var methodOf = restParam(function(object, args) {
      return function(path) {
        return invokePath(object, path, args);
      };
    });
    function mixin(object, source, options) {
      if (options == null) {
        var isObj = isObject(source),
            props = isObj ? keys(source) : undefined,
            methodNames = (props && props.length) ? baseFunctions(source, props) : undefined;
        if (!(methodNames ? methodNames.length : isObj)) {
          methodNames = false;
          options = source;
          source = object;
          object = this;
        }
      }
      if (!methodNames) {
        methodNames = baseFunctions(source, keys(source));
      }
      var chain = true,
          index = -1,
          isFunc = isFunction(object),
          length = methodNames.length;
      if (options === false) {
        chain = false;
      } else if (isObject(options) && 'chain' in options) {
        chain = options.chain;
      }
      while (++index < length) {
        var methodName = methodNames[index],
            func = source[methodName];
        object[methodName] = func;
        if (isFunc) {
          object.prototype[methodName] = (function(func) {
            return function() {
              var chainAll = this.__chain__;
              if (chain || chainAll) {
                var result = object(this.__wrapped__),
                    actions = result.__actions__ = arrayCopy(this.__actions__);
                actions.push({
                  'func': func,
                  'args': arguments,
                  'thisArg': object
                });
                result.__chain__ = chainAll;
                return result;
              }
              return func.apply(object, arrayPush([this.value()], arguments));
            };
          }(func));
        }
      }
      return object;
    }
    function noConflict() {
      root._ = oldDash;
      return this;
    }
    function noop() {}
    function property(path) {
      return isKey(path) ? baseProperty(path) : basePropertyDeep(path);
    }
    function propertyOf(object) {
      return function(path) {
        return baseGet(object, toPath(path), path + '');
      };
    }
    function range(start, end, step) {
      if (step && isIterateeCall(start, end, step)) {
        end = step = undefined;
      }
      start = +start || 0;
      step = step == null ? 1 : (+step || 0);
      if (end == null) {
        end = start;
        start = 0;
      } else {
        end = +end || 0;
      }
      var index = -1,
          length = nativeMax(nativeCeil((end - start) / (step || 1)), 0),
          result = Array(length);
      while (++index < length) {
        result[index] = start;
        start += step;
      }
      return result;
    }
    function times(n, iteratee, thisArg) {
      n = nativeFloor(n);
      if (n < 1 || !nativeIsFinite(n)) {
        return [];
      }
      var index = -1,
          result = Array(nativeMin(n, MAX_ARRAY_LENGTH));
      iteratee = bindCallback(iteratee, thisArg, 1);
      while (++index < n) {
        if (index < MAX_ARRAY_LENGTH) {
          result[index] = iteratee(index);
        } else {
          iteratee(index);
        }
      }
      return result;
    }
    function uniqueId(prefix) {
      var id = ++idCounter;
      return baseToString(prefix) + id;
    }
    function add(augend, addend) {
      return (+augend || 0) + (+addend || 0);
    }
    var ceil = createRound('ceil');
    var floor = createRound('floor');
    var max = createExtremum(gt, NEGATIVE_INFINITY);
    var min = createExtremum(lt, POSITIVE_INFINITY);
    var round = createRound('round');
    function sum(collection, iteratee, thisArg) {
      if (thisArg && isIterateeCall(collection, iteratee, thisArg)) {
        iteratee = undefined;
      }
      iteratee = getCallback(iteratee, thisArg, 3);
      return iteratee.length == 1 ? arraySum(isArray(collection) ? collection : toIterable(collection), iteratee) : baseSum(collection, iteratee);
    }
    lodash.prototype = baseLodash.prototype;
    LodashWrapper.prototype = baseCreate(baseLodash.prototype);
    LodashWrapper.prototype.constructor = LodashWrapper;
    LazyWrapper.prototype = baseCreate(baseLodash.prototype);
    LazyWrapper.prototype.constructor = LazyWrapper;
    MapCache.prototype['delete'] = mapDelete;
    MapCache.prototype.get = mapGet;
    MapCache.prototype.has = mapHas;
    MapCache.prototype.set = mapSet;
    SetCache.prototype.push = cachePush;
    memoize.Cache = MapCache;
    lodash.after = after;
    lodash.ary = ary;
    lodash.assign = assign;
    lodash.at = at;
    lodash.before = before;
    lodash.bind = bind;
    lodash.bindAll = bindAll;
    lodash.bindKey = bindKey;
    lodash.callback = callback;
    lodash.chain = chain;
    lodash.chunk = chunk;
    lodash.compact = compact;
    lodash.constant = constant;
    lodash.countBy = countBy;
    lodash.create = create;
    lodash.curry = curry;
    lodash.curryRight = curryRight;
    lodash.debounce = debounce;
    lodash.defaults = defaults;
    lodash.defaultsDeep = defaultsDeep;
    lodash.defer = defer;
    lodash.delay = delay;
    lodash.difference = difference;
    lodash.drop = drop;
    lodash.dropRight = dropRight;
    lodash.dropRightWhile = dropRightWhile;
    lodash.dropWhile = dropWhile;
    lodash.fill = fill;
    lodash.filter = filter;
    lodash.flatten = flatten;
    lodash.flattenDeep = flattenDeep;
    lodash.flow = flow;
    lodash.flowRight = flowRight;
    lodash.forEach = forEach;
    lodash.forEachRight = forEachRight;
    lodash.forIn = forIn;
    lodash.forInRight = forInRight;
    lodash.forOwn = forOwn;
    lodash.forOwnRight = forOwnRight;
    lodash.functions = functions;
    lodash.groupBy = groupBy;
    lodash.indexBy = indexBy;
    lodash.initial = initial;
    lodash.intersection = intersection;
    lodash.invert = invert;
    lodash.invoke = invoke;
    lodash.keys = keys;
    lodash.keysIn = keysIn;
    lodash.map = map;
    lodash.mapKeys = mapKeys;
    lodash.mapValues = mapValues;
    lodash.matches = matches;
    lodash.matchesProperty = matchesProperty;
    lodash.memoize = memoize;
    lodash.merge = merge;
    lodash.method = method;
    lodash.methodOf = methodOf;
    lodash.mixin = mixin;
    lodash.modArgs = modArgs;
    lodash.negate = negate;
    lodash.omit = omit;
    lodash.once = once;
    lodash.pairs = pairs;
    lodash.partial = partial;
    lodash.partialRight = partialRight;
    lodash.partition = partition;
    lodash.pick = pick;
    lodash.pluck = pluck;
    lodash.property = property;
    lodash.propertyOf = propertyOf;
    lodash.pull = pull;
    lodash.pullAt = pullAt;
    lodash.range = range;
    lodash.rearg = rearg;
    lodash.reject = reject;
    lodash.remove = remove;
    lodash.rest = rest;
    lodash.restParam = restParam;
    lodash.set = set;
    lodash.shuffle = shuffle;
    lodash.slice = slice;
    lodash.sortBy = sortBy;
    lodash.sortByAll = sortByAll;
    lodash.sortByOrder = sortByOrder;
    lodash.spread = spread;
    lodash.take = take;
    lodash.takeRight = takeRight;
    lodash.takeRightWhile = takeRightWhile;
    lodash.takeWhile = takeWhile;
    lodash.tap = tap;
    lodash.throttle = throttle;
    lodash.thru = thru;
    lodash.times = times;
    lodash.toArray = toArray;
    lodash.toPlainObject = toPlainObject;
    lodash.transform = transform;
    lodash.union = union;
    lodash.uniq = uniq;
    lodash.unzip = unzip;
    lodash.unzipWith = unzipWith;
    lodash.values = values;
    lodash.valuesIn = valuesIn;
    lodash.where = where;
    lodash.without = without;
    lodash.wrap = wrap;
    lodash.xor = xor;
    lodash.zip = zip;
    lodash.zipObject = zipObject;
    lodash.zipWith = zipWith;
    lodash.backflow = flowRight;
    lodash.collect = map;
    lodash.compose = flowRight;
    lodash.each = forEach;
    lodash.eachRight = forEachRight;
    lodash.extend = assign;
    lodash.iteratee = callback;
    lodash.methods = functions;
    lodash.object = zipObject;
    lodash.select = filter;
    lodash.tail = rest;
    lodash.unique = uniq;
    mixin(lodash, lodash);
    lodash.add = add;
    lodash.attempt = attempt;
    lodash.camelCase = camelCase;
    lodash.capitalize = capitalize;
    lodash.ceil = ceil;
    lodash.clone = clone;
    lodash.cloneDeep = cloneDeep;
    lodash.deburr = deburr;
    lodash.endsWith = endsWith;
    lodash.escape = escape;
    lodash.escapeRegExp = escapeRegExp;
    lodash.every = every;
    lodash.find = find;
    lodash.findIndex = findIndex;
    lodash.findKey = findKey;
    lodash.findLast = findLast;
    lodash.findLastIndex = findLastIndex;
    lodash.findLastKey = findLastKey;
    lodash.findWhere = findWhere;
    lodash.first = first;
    lodash.floor = floor;
    lodash.get = get;
    lodash.gt = gt;
    lodash.gte = gte;
    lodash.has = has;
    lodash.identity = identity;
    lodash.includes = includes;
    lodash.indexOf = indexOf;
    lodash.inRange = inRange;
    lodash.isArguments = isArguments;
    lodash.isArray = isArray;
    lodash.isBoolean = isBoolean;
    lodash.isDate = isDate;
    lodash.isElement = isElement;
    lodash.isEmpty = isEmpty;
    lodash.isEqual = isEqual;
    lodash.isError = isError;
    lodash.isFinite = isFinite;
    lodash.isFunction = isFunction;
    lodash.isMatch = isMatch;
    lodash.isNaN = isNaN;
    lodash.isNative = isNative;
    lodash.isNull = isNull;
    lodash.isNumber = isNumber;
    lodash.isObject = isObject;
    lodash.isPlainObject = isPlainObject;
    lodash.isRegExp = isRegExp;
    lodash.isString = isString;
    lodash.isTypedArray = isTypedArray;
    lodash.isUndefined = isUndefined;
    lodash.kebabCase = kebabCase;
    lodash.last = last;
    lodash.lastIndexOf = lastIndexOf;
    lodash.lt = lt;
    lodash.lte = lte;
    lodash.max = max;
    lodash.min = min;
    lodash.noConflict = noConflict;
    lodash.noop = noop;
    lodash.now = now;
    lodash.pad = pad;
    lodash.padLeft = padLeft;
    lodash.padRight = padRight;
    lodash.parseInt = parseInt;
    lodash.random = random;
    lodash.reduce = reduce;
    lodash.reduceRight = reduceRight;
    lodash.repeat = repeat;
    lodash.result = result;
    lodash.round = round;
    lodash.runInContext = runInContext;
    lodash.size = size;
    lodash.snakeCase = snakeCase;
    lodash.some = some;
    lodash.sortedIndex = sortedIndex;
    lodash.sortedLastIndex = sortedLastIndex;
    lodash.startCase = startCase;
    lodash.startsWith = startsWith;
    lodash.sum = sum;
    lodash.template = template;
    lodash.trim = trim;
    lodash.trimLeft = trimLeft;
    lodash.trimRight = trimRight;
    lodash.trunc = trunc;
    lodash.unescape = unescape;
    lodash.uniqueId = uniqueId;
    lodash.words = words;
    lodash.all = every;
    lodash.any = some;
    lodash.contains = includes;
    lodash.eq = isEqual;
    lodash.detect = find;
    lodash.foldl = reduce;
    lodash.foldr = reduceRight;
    lodash.head = first;
    lodash.include = includes;
    lodash.inject = reduce;
    mixin(lodash, (function() {
      var source = {};
      baseForOwn(lodash, function(func, methodName) {
        if (!lodash.prototype[methodName]) {
          source[methodName] = func;
        }
      });
      return source;
    }()), false);
    lodash.sample = sample;
    lodash.prototype.sample = function(n) {
      if (!this.__chain__ && n == null) {
        return sample(this.value());
      }
      return this.thru(function(value) {
        return sample(value, n);
      });
    };
    lodash.VERSION = VERSION;
    arrayEach(['bind', 'bindKey', 'curry', 'curryRight', 'partial', 'partialRight'], function(methodName) {
      lodash[methodName].placeholder = lodash;
    });
    arrayEach(['drop', 'take'], function(methodName, index) {
      LazyWrapper.prototype[methodName] = function(n) {
        var filtered = this.__filtered__;
        if (filtered && !index) {
          return new LazyWrapper(this);
        }
        n = n == null ? 1 : nativeMax(nativeFloor(n) || 0, 0);
        var result = this.clone();
        if (filtered) {
          result.__takeCount__ = nativeMin(result.__takeCount__, n);
        } else {
          result.__views__.push({
            'size': n,
            'type': methodName + (result.__dir__ < 0 ? 'Right' : '')
          });
        }
        return result;
      };
      LazyWrapper.prototype[methodName + 'Right'] = function(n) {
        return this.reverse()[methodName](n).reverse();
      };
    });
    arrayEach(['filter', 'map', 'takeWhile'], function(methodName, index) {
      var type = index + 1,
          isFilter = type != LAZY_MAP_FLAG;
      LazyWrapper.prototype[methodName] = function(iteratee, thisArg) {
        var result = this.clone();
        result.__iteratees__.push({
          'iteratee': getCallback(iteratee, thisArg, 1),
          'type': type
        });
        result.__filtered__ = result.__filtered__ || isFilter;
        return result;
      };
    });
    arrayEach(['first', 'last'], function(methodName, index) {
      var takeName = 'take' + (index ? 'Right' : '');
      LazyWrapper.prototype[methodName] = function() {
        return this[takeName](1).value()[0];
      };
    });
    arrayEach(['initial', 'rest'], function(methodName, index) {
      var dropName = 'drop' + (index ? '' : 'Right');
      LazyWrapper.prototype[methodName] = function() {
        return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1);
      };
    });
    arrayEach(['pluck', 'where'], function(methodName, index) {
      var operationName = index ? 'filter' : 'map',
          createCallback = index ? baseMatches : property;
      LazyWrapper.prototype[methodName] = function(value) {
        return this[operationName](createCallback(value));
      };
    });
    LazyWrapper.prototype.compact = function() {
      return this.filter(identity);
    };
    LazyWrapper.prototype.reject = function(predicate, thisArg) {
      predicate = getCallback(predicate, thisArg, 1);
      return this.filter(function(value) {
        return !predicate(value);
      });
    };
    LazyWrapper.prototype.slice = function(start, end) {
      start = start == null ? 0 : (+start || 0);
      var result = this;
      if (result.__filtered__ && (start > 0 || end < 0)) {
        return new LazyWrapper(result);
      }
      if (start < 0) {
        result = result.takeRight(-start);
      } else if (start) {
        result = result.drop(start);
      }
      if (end !== undefined) {
        end = (+end || 0);
        result = end < 0 ? result.dropRight(-end) : result.take(end - start);
      }
      return result;
    };
    LazyWrapper.prototype.takeRightWhile = function(predicate, thisArg) {
      return this.reverse().takeWhile(predicate, thisArg).reverse();
    };
    LazyWrapper.prototype.toArray = function() {
      return this.take(POSITIVE_INFINITY);
    };
    baseForOwn(LazyWrapper.prototype, function(func, methodName) {
      var checkIteratee = /^(?:filter|map|reject)|While$/.test(methodName),
          retUnwrapped = /^(?:first|last)$/.test(methodName),
          lodashFunc = lodash[retUnwrapped ? ('take' + (methodName == 'last' ? 'Right' : '')) : methodName];
      if (!lodashFunc) {
        return;
      }
      lodash.prototype[methodName] = function() {
        var args = retUnwrapped ? [1] : arguments,
            chainAll = this.__chain__,
            value = this.__wrapped__,
            isHybrid = !!this.__actions__.length,
            isLazy = value instanceof LazyWrapper,
            iteratee = args[0],
            useLazy = isLazy || isArray(value);
        if (useLazy && checkIteratee && typeof iteratee == 'function' && iteratee.length != 1) {
          isLazy = useLazy = false;
        }
        var interceptor = function(value) {
          return (retUnwrapped && chainAll) ? lodashFunc(value, 1)[0] : lodashFunc.apply(undefined, arrayPush([value], args));
        };
        var action = {
          'func': thru,
          'args': [interceptor],
          'thisArg': undefined
        },
            onlyLazy = isLazy && !isHybrid;
        if (retUnwrapped && !chainAll) {
          if (onlyLazy) {
            value = value.clone();
            value.__actions__.push(action);
            return func.call(value);
          }
          return lodashFunc.call(undefined, this.value())[0];
        }
        if (!retUnwrapped && useLazy) {
          value = onlyLazy ? value : new LazyWrapper(this);
          var result = func.apply(value, args);
          result.__actions__.push(action);
          return new LodashWrapper(result, chainAll);
        }
        return this.thru(interceptor);
      };
    });
    arrayEach(['join', 'pop', 'push', 'replace', 'shift', 'sort', 'splice', 'split', 'unshift'], function(methodName) {
      var func = (/^(?:replace|split)$/.test(methodName) ? stringProto : arrayProto)[methodName],
          chainName = /^(?:push|sort|unshift)$/.test(methodName) ? 'tap' : 'thru',
          retUnwrapped = /^(?:join|pop|replace|shift)$/.test(methodName);
      lodash.prototype[methodName] = function() {
        var args = arguments;
        if (retUnwrapped && !this.__chain__) {
          return func.apply(this.value(), args);
        }
        return this[chainName](function(value) {
          return func.apply(value, args);
        });
      };
    });
    baseForOwn(LazyWrapper.prototype, function(func, methodName) {
      var lodashFunc = lodash[methodName];
      if (lodashFunc) {
        var key = lodashFunc.name,
            names = realNames[key] || (realNames[key] = []);
        names.push({
          'name': methodName,
          'func': lodashFunc
        });
      }
    });
    realNames[createHybridWrapper(undefined, BIND_KEY_FLAG).name] = [{
      'name': 'wrapper',
      'func': undefined
    }];
    LazyWrapper.prototype.clone = lazyClone;
    LazyWrapper.prototype.reverse = lazyReverse;
    LazyWrapper.prototype.value = lazyValue;
    lodash.prototype.chain = wrapperChain;
    lodash.prototype.commit = wrapperCommit;
    lodash.prototype.concat = wrapperConcat;
    lodash.prototype.plant = wrapperPlant;
    lodash.prototype.reverse = wrapperReverse;
    lodash.prototype.toString = wrapperToString;
    lodash.prototype.run = lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue;
    lodash.prototype.collect = lodash.prototype.map;
    lodash.prototype.head = lodash.prototype.first;
    lodash.prototype.select = lodash.prototype.filter;
    lodash.prototype.tail = lodash.prototype.rest;
    return lodash;
  }
  var _ = runInContext();
  if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
    root._ = _;
    define("32", [], function() {
      return _;
    });
  } else if (freeExports && freeModule) {
    if (moduleExports) {
      (freeModule.exports = _)._ = _;
    } else {
      freeExports._ = _;
    }
  } else {
    root._ = _;
  }
}.call(this));

})();
$__System.registerDynamic("33", [], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  module.exports = "<div class=\"notification\">\n\t<h3 class=\"name\" style=\"margin: 0\"></h3>\n\t<div class=\"value-display\" style=\"text-align: right; font-family: monospace\">\n\t\t<span class=\"value\" style=\"font-size: 200%\"></span>\n\t\t<span class=\"unit\"></span>\n\t</div>\n\t<div class=\"value-bar\" style=\"display: none\">\n\t\t<progress style=\"display: inline-block; width: 100%\"></progress>\n\t</div>\n</div>\n";
  return module.exports;
});

$__System.registerDynamic("34", [], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  module.exports = "<div class=\"overlay-content\">\n\t<div class=\"page-header\">\n\t\t<h1>\n\t\t\t<span class=\"title\"></span>\n\t\t\t<small class=\"subtitle\"></small>\n\t\t</h1>\n\t</div>\n\t<div class=\"content\"></div>\n\t<button class=\"btn btn-lg btn-success pull-right accept-button\" style=\"min-width: 10em; display: inline-block;\">\n\t\t<span class=\"loading\">Loading</span>\n\t\t<span class=\"accept\">OK</span>\n\t</button>\n</div>\n";
  return module.exports;
});

$__System.registerDynamic("35", [], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  module.exports = "<div class=\"overlay-content\">\n\t<div class=\"page-header\">\n\t\t<h1>\n\t\t\t<span class=\"title\"></span>\n\t\t\t<small class=\"subtitle\"></small>\n\t\t</h1>\n\t</div>\n\t<div class=\"text\"></div>\n\t<form class=\"content\" autocomplete=\"off\">\n\t<div class=\"inputs\" style=\"clear: both; padding: 30px;\"></div>\n\t<button type=\"submit\" value=\"accept\" class=\"btn btn-lg btn-success pull-right accept-button\" style=\"min-width: 10em; display: inline-block;\">\n\t\t<span class=\"accept\">OK</span>\n\t</button>\n\t<button type=\"submit\" class=\"btn btn-lg btn-default pull-left cancel-button\" style=\"min-width: 10em; display: inline-block;\">\n\t\t<span class=\"cancel\">Cancel</span>\n\t</button>\n\t</form>\n</div>\n";
  return module.exports;
});

$__System.registerDynamic("36", [], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  module.exports = "<div class=\"notification\">\n\t<h2 class=\"title\"></h2>\n\t<div class=\"content\"></div>\n</div>\n";
  return module.exports;
});

$__System.registerDynamic("24", ["19", "20", "32", "1a", "33", "34", "35", "36"], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  var $,
      P,
      Co,
      template,
      seqr,
      waitFor,
      sleep,
      configTemplate,
      gauge,
      instructionScreen,
      inputDialog,
      taskDialog,
      out$ = typeof exports != 'undefined' && exports || this;
  $ = $__require('19');
  P = $__require('20');
  Co = P.coroutine;
  template = $__require('32').template;
  seqr = $__require('1a');
  out$.waitFor = waitFor = function(f) {
    return new P(function(accept) {
      return f(accept);
    });
  };
  out$.sleep = sleep = function(duration) {
    return new P(function(accept) {
      return setTimeout(accept, duration * 1000);
    });
  };
  configTemplate = function(data, config, parent) {
    var el,
        api;
    el = $(data);
    if (parent != null) {
      parent.append(el);
    }
    api = function(name) {
      return el.find("." + name);
    };
    api.el = el;
    api.result = config.apply(api, [el]);
    return api;
  };
  out$.gauge = gauge = function(arg$, arg1$) {
    var notifications,
        uiUpdate,
        name,
        unit,
        ref$,
        range,
        value,
        format,
        result,
        valel,
        bar;
    notifications = arg$.notifications, uiUpdate = arg$.uiUpdate;
    name = arg1$.name, unit = (ref$ = arg1$.unit) != null ? ref$ : '', range = arg1$.range, value = arg1$.value, format = (ref$ = arg1$.format) != null ? ref$ : function(v) {
      return v;
    };
    result = configTemplate($__require('33'), function() {
      this('name').text(name);
      return this('unit').text(unit);
    });
    if (notifications != null) {
      notifications.append(result.el);
    }
    valel = result('value');
    uiUpdate(function() {
      return valel.text(format(value()));
    });
    if (range) {
      bar = result('value-bar').show().find('progress').attr({
        min: range[0],
        max: range[1]
      });
      uiUpdate(function() {
        var val;
        val = value();
        if (val != null && isFinite(val)) {
          return bar.val(val);
        } else {
          return bar.val("");
        }
      });
    }
    result.normal = function() {
      return result.el.css({"background-color": ""});
    };
    result.warning = function() {
      return result.el.css({"background-color": "rgba(242, 10, 10, 0.8)"});
    };
    return result;
  };
  out$.instructionScreen = instructionScreen = seqr.bind(function*(arg$, cb) {
    var container,
        controls,
        background,
        api,
        btn,
        this$ = this;
    container = arg$.container, controls = arg$.controls;
    background = $('<div class="overlay-screen">');
    container.append(background);
    api = configTemplate($__require('34'), cb, background);
    btn = api('accept-button');
    btn.prop("disabled", true);
    api('accept').hide();
    (yield waitFor(bind$(background, 'fadeIn')));
    (yield P.resolve(api.result));
    btn.prop("disabled", false);
    btn.focus();
    api('loading').hide();
    api('accept').show();
    btn.one("click", function() {
      return this$['let']('accept');
    });
    controls.change(function(btn, isOn) {
      if (btn === 'catch' && isOn) {
        this$['let']('accept');
        return false;
      }
    });
    (yield this.get('accept'));
    (yield new P(function(accept) {
      return background.fadeOut(accept);
    }));
    return background.remove();
  });
  out$.inputDialog = inputDialog = seqr.bind(function*(arg$, cb) {
    var container,
        controls,
        logger,
        api,
        el,
        form,
        background,
        btn,
        canceled,
        result,
        this$ = this;
    container = arg$.container, controls = arg$.controls, logger = arg$.logger;
    api = configTemplate($__require('35'), cb);
    el = api.el;
    form = el.find("form");
    form.submit(function(e) {
      return e.preventDefault();
    });
    background = $('<div class="overlay-screen">');
    background.append(el);
    container.append(background);
    background.hide();
    btn = api('accept-button');
    canceled = false;
    api('cancel-button').click(function() {
      return canceled = true;
    });
    (yield waitFor(bind$(background, 'fadeIn')));
    form.on("submit", function(e) {
      var result;
      result = {
        canceled: canceled,
        formData: form.serializeArray()
      };
      logger.write(result);
      return this$['let']('result', result);
    });
    result = (yield this.get('result'));
    (yield new P(function(accept) {
      return background.fadeOut(accept);
    }));
    background.remove();
    return result;
  });
  out$.taskDialog = taskDialog = Co(function*(arg$, cb) {
    var notifications,
        api,
        ref$,
        el,
        result;
    notifications = arg$.notifications;
    ref$ = api = configTemplate($__require('36'), cb), el = ref$.el, result = ref$.result;
    el.hide();
    if (notifications != null) {
      notifications.append(el);
    }
    (yield waitFor(bind$(el, 'fadeIn')));
    (yield P.resolve(result));
    (yield waitFor(bind$(el, 'fadeOut')));
    return el.remove();
  });
  function bind$(obj, key, target) {
    return function() {
      return (target || obj)[key].apply(obj, arguments);
    };
  }
  return module.exports;
});

$__System.registerDynamic("25", [], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  var THREE = {REVISION: '78'};
  if (typeof define === 'function' && define.amd) {
    define('three', THREE);
  } else if ('undefined' !== typeof exports && 'undefined' !== typeof module) {
    module.exports = THREE;
  }
  if (Number.EPSILON === undefined) {
    Number.EPSILON = Math.pow(2, -52);
  }
  if (Math.sign === undefined) {
    Math.sign = function(x) {
      return (x < 0) ? -1 : (x > 0) ? 1 : +x;
    };
  }
  if (Function.prototype.name === undefined) {
    Object.defineProperty(Function.prototype, 'name', {get: function() {
        return this.toString().match(/^\s*function\s*(\S*)\s*\(/)[1];
      }});
  }
  if (Object.assign === undefined) {
    (function() {
      Object.assign = function(target) {
        'use strict';
        if (target === undefined || target === null) {
          throw new TypeError('Cannot convert undefined or null to object');
        }
        var output = Object(target);
        for (var index = 1; index < arguments.length; index++) {
          var source = arguments[index];
          if (source !== undefined && source !== null) {
            for (var nextKey in source) {
              if (Object.prototype.hasOwnProperty.call(source, nextKey)) {
                output[nextKey] = source[nextKey];
              }
            }
          }
        }
        return output;
      };
    })();
  }
  Object.assign(THREE, {
    MOUSE: {
      LEFT: 0,
      MIDDLE: 1,
      RIGHT: 2
    },
    CullFaceNone: 0,
    CullFaceBack: 1,
    CullFaceFront: 2,
    CullFaceFrontBack: 3,
    FrontFaceDirectionCW: 0,
    FrontFaceDirectionCCW: 1,
    BasicShadowMap: 0,
    PCFShadowMap: 1,
    PCFSoftShadowMap: 2,
    FrontSide: 0,
    BackSide: 1,
    DoubleSide: 2,
    FlatShading: 1,
    SmoothShading: 2,
    NoColors: 0,
    FaceColors: 1,
    VertexColors: 2,
    NoBlending: 0,
    NormalBlending: 1,
    AdditiveBlending: 2,
    SubtractiveBlending: 3,
    MultiplyBlending: 4,
    CustomBlending: 5,
    AddEquation: 100,
    SubtractEquation: 101,
    ReverseSubtractEquation: 102,
    MinEquation: 103,
    MaxEquation: 104,
    ZeroFactor: 200,
    OneFactor: 201,
    SrcColorFactor: 202,
    OneMinusSrcColorFactor: 203,
    SrcAlphaFactor: 204,
    OneMinusSrcAlphaFactor: 205,
    DstAlphaFactor: 206,
    OneMinusDstAlphaFactor: 207,
    DstColorFactor: 208,
    OneMinusDstColorFactor: 209,
    SrcAlphaSaturateFactor: 210,
    NeverDepth: 0,
    AlwaysDepth: 1,
    LessDepth: 2,
    LessEqualDepth: 3,
    EqualDepth: 4,
    GreaterEqualDepth: 5,
    GreaterDepth: 6,
    NotEqualDepth: 7,
    MultiplyOperation: 0,
    MixOperation: 1,
    AddOperation: 2,
    NoToneMapping: 0,
    LinearToneMapping: 1,
    ReinhardToneMapping: 2,
    Uncharted2ToneMapping: 3,
    CineonToneMapping: 4,
    UVMapping: 300,
    CubeReflectionMapping: 301,
    CubeRefractionMapping: 302,
    EquirectangularReflectionMapping: 303,
    EquirectangularRefractionMapping: 304,
    SphericalReflectionMapping: 305,
    CubeUVReflectionMapping: 306,
    CubeUVRefractionMapping: 307,
    RepeatWrapping: 1000,
    ClampToEdgeWrapping: 1001,
    MirroredRepeatWrapping: 1002,
    NearestFilter: 1003,
    NearestMipMapNearestFilter: 1004,
    NearestMipMapLinearFilter: 1005,
    LinearFilter: 1006,
    LinearMipMapNearestFilter: 1007,
    LinearMipMapLinearFilter: 1008,
    UnsignedByteType: 1009,
    ByteType: 1010,
    ShortType: 1011,
    UnsignedShortType: 1012,
    IntType: 1013,
    UnsignedIntType: 1014,
    FloatType: 1015,
    HalfFloatType: 1025,
    UnsignedShort4444Type: 1016,
    UnsignedShort5551Type: 1017,
    UnsignedShort565Type: 1018,
    AlphaFormat: 1019,
    RGBFormat: 1020,
    RGBAFormat: 1021,
    LuminanceFormat: 1022,
    LuminanceAlphaFormat: 1023,
    RGBEFormat: THREE.RGBAFormat,
    DepthFormat: 1026,
    RGB_S3TC_DXT1_Format: 2001,
    RGBA_S3TC_DXT1_Format: 2002,
    RGBA_S3TC_DXT3_Format: 2003,
    RGBA_S3TC_DXT5_Format: 2004,
    RGB_PVRTC_4BPPV1_Format: 2100,
    RGB_PVRTC_2BPPV1_Format: 2101,
    RGBA_PVRTC_4BPPV1_Format: 2102,
    RGBA_PVRTC_2BPPV1_Format: 2103,
    RGB_ETC1_Format: 2151,
    LoopOnce: 2200,
    LoopRepeat: 2201,
    LoopPingPong: 2202,
    InterpolateDiscrete: 2300,
    InterpolateLinear: 2301,
    InterpolateSmooth: 2302,
    ZeroCurvatureEnding: 2400,
    ZeroSlopeEnding: 2401,
    WrapAroundEnding: 2402,
    TrianglesDrawMode: 0,
    TriangleStripDrawMode: 1,
    TriangleFanDrawMode: 2,
    LinearEncoding: 3000,
    sRGBEncoding: 3001,
    GammaEncoding: 3007,
    RGBEEncoding: 3002,
    LogLuvEncoding: 3003,
    RGBM7Encoding: 3004,
    RGBM16Encoding: 3005,
    RGBDEncoding: 3006,
    BasicDepthPacking: 3200,
    RGBADepthPacking: 3201
  });
  THREE.Color = function(r, g, b) {
    if (g === undefined && b === undefined) {
      return this.set(r);
    }
    return this.setRGB(r, g, b);
  };
  THREE.Color.prototype = {
    constructor: THREE.Color,
    r: 1,
    g: 1,
    b: 1,
    set: function(value) {
      if (value instanceof THREE.Color) {
        this.copy(value);
      } else if (typeof value === 'number') {
        this.setHex(value);
      } else if (typeof value === 'string') {
        this.setStyle(value);
      }
      return this;
    },
    setScalar: function(scalar) {
      this.r = scalar;
      this.g = scalar;
      this.b = scalar;
    },
    setHex: function(hex) {
      hex = Math.floor(hex);
      this.r = (hex >> 16 & 255) / 255;
      this.g = (hex >> 8 & 255) / 255;
      this.b = (hex & 255) / 255;
      return this;
    },
    setRGB: function(r, g, b) {
      this.r = r;
      this.g = g;
      this.b = b;
      return this;
    },
    setHSL: function() {
      function hue2rgb(p, q, t) {
        if (t < 0)
          t += 1;
        if (t > 1)
          t -= 1;
        if (t < 1 / 6)
          return p + (q - p) * 6 * t;
        if (t < 1 / 2)
          return q;
        if (t < 2 / 3)
          return p + (q - p) * 6 * (2 / 3 - t);
        return p;
      }
      return function setHSL(h, s, l) {
        h = THREE.Math.euclideanModulo(h, 1);
        s = THREE.Math.clamp(s, 0, 1);
        l = THREE.Math.clamp(l, 0, 1);
        if (s === 0) {
          this.r = this.g = this.b = l;
        } else {
          var p = l <= 0.5 ? l * (1 + s) : l + s - (l * s);
          var q = (2 * l) - p;
          this.r = hue2rgb(q, p, h + 1 / 3);
          this.g = hue2rgb(q, p, h);
          this.b = hue2rgb(q, p, h - 1 / 3);
        }
        return this;
      };
    }(),
    setStyle: function(style) {
      function handleAlpha(string) {
        if (string === undefined)
          return;
        if (parseFloat(string) < 1) {
          console.warn('THREE.Color: Alpha component of ' + style + ' will be ignored.');
        }
      }
      var m;
      if (m = /^((?:rgb|hsl)a?)\(\s*([^\)]*)\)/.exec(style)) {
        var color;
        var name = m[1];
        var components = m[2];
        switch (name) {
          case 'rgb':
          case 'rgba':
            if (color = /^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec(components)) {
              this.r = Math.min(255, parseInt(color[1], 10)) / 255;
              this.g = Math.min(255, parseInt(color[2], 10)) / 255;
              this.b = Math.min(255, parseInt(color[3], 10)) / 255;
              handleAlpha(color[5]);
              return this;
            }
            if (color = /^(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec(components)) {
              this.r = Math.min(100, parseInt(color[1], 10)) / 100;
              this.g = Math.min(100, parseInt(color[2], 10)) / 100;
              this.b = Math.min(100, parseInt(color[3], 10)) / 100;
              handleAlpha(color[5]);
              return this;
            }
            break;
          case 'hsl':
          case 'hsla':
            if (color = /^([0-9]*\.?[0-9]+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec(components)) {
              var h = parseFloat(color[1]) / 360;
              var s = parseInt(color[2], 10) / 100;
              var l = parseInt(color[3], 10) / 100;
              handleAlpha(color[5]);
              return this.setHSL(h, s, l);
            }
            break;
        }
      } else if (m = /^\#([A-Fa-f0-9]+)$/.exec(style)) {
        var hex = m[1];
        var size = hex.length;
        if (size === 3) {
          this.r = parseInt(hex.charAt(0) + hex.charAt(0), 16) / 255;
          this.g = parseInt(hex.charAt(1) + hex.charAt(1), 16) / 255;
          this.b = parseInt(hex.charAt(2) + hex.charAt(2), 16) / 255;
          return this;
        } else if (size === 6) {
          this.r = parseInt(hex.charAt(0) + hex.charAt(1), 16) / 255;
          this.g = parseInt(hex.charAt(2) + hex.charAt(3), 16) / 255;
          this.b = parseInt(hex.charAt(4) + hex.charAt(5), 16) / 255;
          return this;
        }
      }
      if (style && style.length > 0) {
        var hex = THREE.ColorKeywords[style];
        if (hex !== undefined) {
          this.setHex(hex);
        } else {
          console.warn('THREE.Color: Unknown color ' + style);
        }
      }
      return this;
    },
    clone: function() {
      return new this.constructor(this.r, this.g, this.b);
    },
    copy: function(color) {
      this.r = color.r;
      this.g = color.g;
      this.b = color.b;
      return this;
    },
    copyGammaToLinear: function(color, gammaFactor) {
      if (gammaFactor === undefined)
        gammaFactor = 2.0;
      this.r = Math.pow(color.r, gammaFactor);
      this.g = Math.pow(color.g, gammaFactor);
      this.b = Math.pow(color.b, gammaFactor);
      return this;
    },
    copyLinearToGamma: function(color, gammaFactor) {
      if (gammaFactor === undefined)
        gammaFactor = 2.0;
      var safeInverse = (gammaFactor > 0) ? (1.0 / gammaFactor) : 1.0;
      this.r = Math.pow(color.r, safeInverse);
      this.g = Math.pow(color.g, safeInverse);
      this.b = Math.pow(color.b, safeInverse);
      return this;
    },
    convertGammaToLinear: function() {
      var r = this.r,
          g = this.g,
          b = this.b;
      this.r = r * r;
      this.g = g * g;
      this.b = b * b;
      return this;
    },
    convertLinearToGamma: function() {
      this.r = Math.sqrt(this.r);
      this.g = Math.sqrt(this.g);
      this.b = Math.sqrt(this.b);
      return this;
    },
    getHex: function() {
      return (this.r * 255) << 16 ^ (this.g * 255) << 8 ^ (this.b * 255) << 0;
    },
    getHexString: function() {
      return ('000000' + this.getHex().toString(16)).slice(-6);
    },
    getHSL: function(optionalTarget) {
      var hsl = optionalTarget || {
        h: 0,
        s: 0,
        l: 0
      };
      var r = this.r,
          g = this.g,
          b = this.b;
      var max = Math.max(r, g, b);
      var min = Math.min(r, g, b);
      var hue,
          saturation;
      var lightness = (min + max) / 2.0;
      if (min === max) {
        hue = 0;
        saturation = 0;
      } else {
        var delta = max - min;
        saturation = lightness <= 0.5 ? delta / (max + min) : delta / (2 - max - min);
        switch (max) {
          case r:
            hue = (g - b) / delta + (g < b ? 6 : 0);
            break;
          case g:
            hue = (b - r) / delta + 2;
            break;
          case b:
            hue = (r - g) / delta + 4;
            break;
        }
        hue /= 6;
      }
      hsl.h = hue;
      hsl.s = saturation;
      hsl.l = lightness;
      return hsl;
    },
    getStyle: function() {
      return 'rgb(' + ((this.r * 255) | 0) + ',' + ((this.g * 255) | 0) + ',' + ((this.b * 255) | 0) + ')';
    },
    offsetHSL: function(h, s, l) {
      var hsl = this.getHSL();
      hsl.h += h;
      hsl.s += s;
      hsl.l += l;
      this.setHSL(hsl.h, hsl.s, hsl.l);
      return this;
    },
    add: function(color) {
      this.r += color.r;
      this.g += color.g;
      this.b += color.b;
      return this;
    },
    addColors: function(color1, color2) {
      this.r = color1.r + color2.r;
      this.g = color1.g + color2.g;
      this.b = color1.b + color2.b;
      return this;
    },
    addScalar: function(s) {
      this.r += s;
      this.g += s;
      this.b += s;
      return this;
    },
    multiply: function(color) {
      this.r *= color.r;
      this.g *= color.g;
      this.b *= color.b;
      return this;
    },
    multiplyScalar: function(s) {
      this.r *= s;
      this.g *= s;
      this.b *= s;
      return this;
    },
    lerp: function(color, alpha) {
      this.r += (color.r - this.r) * alpha;
      this.g += (color.g - this.g) * alpha;
      this.b += (color.b - this.b) * alpha;
      return this;
    },
    equals: function(c) {
      return (c.r === this.r) && (c.g === this.g) && (c.b === this.b);
    },
    fromArray: function(array, offset) {
      if (offset === undefined)
        offset = 0;
      this.r = array[offset];
      this.g = array[offset + 1];
      this.b = array[offset + 2];
      return this;
    },
    toArray: function(array, offset) {
      if (array === undefined)
        array = [];
      if (offset === undefined)
        offset = 0;
      array[offset] = this.r;
      array[offset + 1] = this.g;
      array[offset + 2] = this.b;
      return array;
    }
  };
  THREE.ColorKeywords = {
    'aliceblue': 0xF0F8FF,
    'antiquewhite': 0xFAEBD7,
    'aqua': 0x00FFFF,
    'aquamarine': 0x7FFFD4,
    'azure': 0xF0FFFF,
    'beige': 0xF5F5DC,
    'bisque': 0xFFE4C4,
    'black': 0x000000,
    'blanchedalmond': 0xFFEBCD,
    'blue': 0x0000FF,
    'blueviolet': 0x8A2BE2,
    'brown': 0xA52A2A,
    'burlywood': 0xDEB887,
    'cadetblue': 0x5F9EA0,
    'chartreuse': 0x7FFF00,
    'chocolate': 0xD2691E,
    'coral': 0xFF7F50,
    'cornflowerblue': 0x6495ED,
    'cornsilk': 0xFFF8DC,
    'crimson': 0xDC143C,
    'cyan': 0x00FFFF,
    'darkblue': 0x00008B,
    'darkcyan': 0x008B8B,
    'darkgoldenrod': 0xB8860B,
    'darkgray': 0xA9A9A9,
    'darkgreen': 0x006400,
    'darkgrey': 0xA9A9A9,
    'darkkhaki': 0xBDB76B,
    'darkmagenta': 0x8B008B,
    'darkolivegreen': 0x556B2F,
    'darkorange': 0xFF8C00,
    'darkorchid': 0x9932CC,
    'darkred': 0x8B0000,
    'darksalmon': 0xE9967A,
    'darkseagreen': 0x8FBC8F,
    'darkslateblue': 0x483D8B,
    'darkslategray': 0x2F4F4F,
    'darkslategrey': 0x2F4F4F,
    'darkturquoise': 0x00CED1,
    'darkviolet': 0x9400D3,
    'deeppink': 0xFF1493,
    'deepskyblue': 0x00BFFF,
    'dimgray': 0x696969,
    'dimgrey': 0x696969,
    'dodgerblue': 0x1E90FF,
    'firebrick': 0xB22222,
    'floralwhite': 0xFFFAF0,
    'forestgreen': 0x228B22,
    'fuchsia': 0xFF00FF,
    'gainsboro': 0xDCDCDC,
    'ghostwhite': 0xF8F8FF,
    'gold': 0xFFD700,
    'goldenrod': 0xDAA520,
    'gray': 0x808080,
    'green': 0x008000,
    'greenyellow': 0xADFF2F,
    'grey': 0x808080,
    'honeydew': 0xF0FFF0,
    'hotpink': 0xFF69B4,
    'indianred': 0xCD5C5C,
    'indigo': 0x4B0082,
    'ivory': 0xFFFFF0,
    'khaki': 0xF0E68C,
    'lavender': 0xE6E6FA,
    'lavenderblush': 0xFFF0F5,
    'lawngreen': 0x7CFC00,
    'lemonchiffon': 0xFFFACD,
    'lightblue': 0xADD8E6,
    'lightcoral': 0xF08080,
    'lightcyan': 0xE0FFFF,
    'lightgoldenrodyellow': 0xFAFAD2,
    'lightgray': 0xD3D3D3,
    'lightgreen': 0x90EE90,
    'lightgrey': 0xD3D3D3,
    'lightpink': 0xFFB6C1,
    'lightsalmon': 0xFFA07A,
    'lightseagreen': 0x20B2AA,
    'lightskyblue': 0x87CEFA,
    'lightslategray': 0x778899,
    'lightslategrey': 0x778899,
    'lightsteelblue': 0xB0C4DE,
    'lightyellow': 0xFFFFE0,
    'lime': 0x00FF00,
    'limegreen': 0x32CD32,
    'linen': 0xFAF0E6,
    'magenta': 0xFF00FF,
    'maroon': 0x800000,
    'mediumaquamarine': 0x66CDAA,
    'mediumblue': 0x0000CD,
    'mediumorchid': 0xBA55D3,
    'mediumpurple': 0x9370DB,
    'mediumseagreen': 0x3CB371,
    'mediumslateblue': 0x7B68EE,
    'mediumspringgreen': 0x00FA9A,
    'mediumturquoise': 0x48D1CC,
    'mediumvioletred': 0xC71585,
    'midnightblue': 0x191970,
    'mintcream': 0xF5FFFA,
    'mistyrose': 0xFFE4E1,
    'moccasin': 0xFFE4B5,
    'navajowhite': 0xFFDEAD,
    'navy': 0x000080,
    'oldlace': 0xFDF5E6,
    'olive': 0x808000,
    'olivedrab': 0x6B8E23,
    'orange': 0xFFA500,
    'orangered': 0xFF4500,
    'orchid': 0xDA70D6,
    'palegoldenrod': 0xEEE8AA,
    'palegreen': 0x98FB98,
    'paleturquoise': 0xAFEEEE,
    'palevioletred': 0xDB7093,
    'papayawhip': 0xFFEFD5,
    'peachpuff': 0xFFDAB9,
    'peru': 0xCD853F,
    'pink': 0xFFC0CB,
    'plum': 0xDDA0DD,
    'powderblue': 0xB0E0E6,
    'purple': 0x800080,
    'red': 0xFF0000,
    'rosybrown': 0xBC8F8F,
    'royalblue': 0x4169E1,
    'saddlebrown': 0x8B4513,
    'salmon': 0xFA8072,
    'sandybrown': 0xF4A460,
    'seagreen': 0x2E8B57,
    'seashell': 0xFFF5EE,
    'sienna': 0xA0522D,
    'silver': 0xC0C0C0,
    'skyblue': 0x87CEEB,
    'slateblue': 0x6A5ACD,
    'slategray': 0x708090,
    'slategrey': 0x708090,
    'snow': 0xFFFAFA,
    'springgreen': 0x00FF7F,
    'steelblue': 0x4682B4,
    'tan': 0xD2B48C,
    'teal': 0x008080,
    'thistle': 0xD8BFD8,
    'tomato': 0xFF6347,
    'turquoise': 0x40E0D0,
    'violet': 0xEE82EE,
    'wheat': 0xF5DEB3,
    'white': 0xFFFFFF,
    'whitesmoke': 0xF5F5F5,
    'yellow': 0xFFFF00,
    'yellowgreen': 0x9ACD32
  };
  THREE.Quaternion = function(x, y, z, w) {
    this._x = x || 0;
    this._y = y || 0;
    this._z = z || 0;
    this._w = (w !== undefined) ? w : 1;
  };
  THREE.Quaternion.prototype = {
    constructor: THREE.Quaternion,
    get x() {
      return this._x;
    },
    set x(value) {
      this._x = value;
      this.onChangeCallback();
    },
    get y() {
      return this._y;
    },
    set y(value) {
      this._y = value;
      this.onChangeCallback();
    },
    get z() {
      return this._z;
    },
    set z(value) {
      this._z = value;
      this.onChangeCallback();
    },
    get w() {
      return this._w;
    },
    set w(value) {
      this._w = value;
      this.onChangeCallback();
    },
    set: function(x, y, z, w) {
      this._x = x;
      this._y = y;
      this._z = z;
      this._w = w;
      this.onChangeCallback();
      return this;
    },
    clone: function() {
      return new this.constructor(this._x, this._y, this._z, this._w);
    },
    copy: function(quaternion) {
      this._x = quaternion.x;
      this._y = quaternion.y;
      this._z = quaternion.z;
      this._w = quaternion.w;
      this.onChangeCallback();
      return this;
    },
    setFromEuler: function(euler, update) {
      if (euler instanceof THREE.Euler === false) {
        throw new Error('THREE.Quaternion: .setFromEuler() now expects a Euler rotation rather than a Vector3 and order.');
      }
      var c1 = Math.cos(euler._x / 2);
      var c2 = Math.cos(euler._y / 2);
      var c3 = Math.cos(euler._z / 2);
      var s1 = Math.sin(euler._x / 2);
      var s2 = Math.sin(euler._y / 2);
      var s3 = Math.sin(euler._z / 2);
      var order = euler.order;
      if (order === 'XYZ') {
        this._x = s1 * c2 * c3 + c1 * s2 * s3;
        this._y = c1 * s2 * c3 - s1 * c2 * s3;
        this._z = c1 * c2 * s3 + s1 * s2 * c3;
        this._w = c1 * c2 * c3 - s1 * s2 * s3;
      } else if (order === 'YXZ') {
        this._x = s1 * c2 * c3 + c1 * s2 * s3;
        this._y = c1 * s2 * c3 - s1 * c2 * s3;
        this._z = c1 * c2 * s3 - s1 * s2 * c3;
        this._w = c1 * c2 * c3 + s1 * s2 * s3;
      } else if (order === 'ZXY') {
        this._x = s1 * c2 * c3 - c1 * s2 * s3;
        this._y = c1 * s2 * c3 + s1 * c2 * s3;
        this._z = c1 * c2 * s3 + s1 * s2 * c3;
        this._w = c1 * c2 * c3 - s1 * s2 * s3;
      } else if (order === 'ZYX') {
        this._x = s1 * c2 * c3 - c1 * s2 * s3;
        this._y = c1 * s2 * c3 + s1 * c2 * s3;
        this._z = c1 * c2 * s3 - s1 * s2 * c3;
        this._w = c1 * c2 * c3 + s1 * s2 * s3;
      } else if (order === 'YZX') {
        this._x = s1 * c2 * c3 + c1 * s2 * s3;
        this._y = c1 * s2 * c3 + s1 * c2 * s3;
        this._z = c1 * c2 * s3 - s1 * s2 * c3;
        this._w = c1 * c2 * c3 - s1 * s2 * s3;
      } else if (order === 'XZY') {
        this._x = s1 * c2 * c3 - c1 * s2 * s3;
        this._y = c1 * s2 * c3 - s1 * c2 * s3;
        this._z = c1 * c2 * s3 + s1 * s2 * c3;
        this._w = c1 * c2 * c3 + s1 * s2 * s3;
      }
      if (update !== false)
        this.onChangeCallback();
      return this;
    },
    setFromAxisAngle: function(axis, angle) {
      var halfAngle = angle / 2,
          s = Math.sin(halfAngle);
      this._x = axis.x * s;
      this._y = axis.y * s;
      this._z = axis.z * s;
      this._w = Math.cos(halfAngle);
      this.onChangeCallback();
      return this;
    },
    setFromRotationMatrix: function(m) {
      var te = m.elements,
          m11 = te[0],
          m12 = te[4],
          m13 = te[8],
          m21 = te[1],
          m22 = te[5],
          m23 = te[9],
          m31 = te[2],
          m32 = te[6],
          m33 = te[10],
          trace = m11 + m22 + m33,
          s;
      if (trace > 0) {
        s = 0.5 / Math.sqrt(trace + 1.0);
        this._w = 0.25 / s;
        this._x = (m32 - m23) * s;
        this._y = (m13 - m31) * s;
        this._z = (m21 - m12) * s;
      } else if (m11 > m22 && m11 > m33) {
        s = 2.0 * Math.sqrt(1.0 + m11 - m22 - m33);
        this._w = (m32 - m23) / s;
        this._x = 0.25 * s;
        this._y = (m12 + m21) / s;
        this._z = (m13 + m31) / s;
      } else if (m22 > m33) {
        s = 2.0 * Math.sqrt(1.0 + m22 - m11 - m33);
        this._w = (m13 - m31) / s;
        this._x = (m12 + m21) / s;
        this._y = 0.25 * s;
        this._z = (m23 + m32) / s;
      } else {
        s = 2.0 * Math.sqrt(1.0 + m33 - m11 - m22);
        this._w = (m21 - m12) / s;
        this._x = (m13 + m31) / s;
        this._y = (m23 + m32) / s;
        this._z = 0.25 * s;
      }
      this.onChangeCallback();
      return this;
    },
    setFromUnitVectors: function() {
      var v1,
          r;
      var EPS = 0.000001;
      return function setFromUnitVectors(vFrom, vTo) {
        if (v1 === undefined)
          v1 = new THREE.Vector3();
        r = vFrom.dot(vTo) + 1;
        if (r < EPS) {
          r = 0;
          if (Math.abs(vFrom.x) > Math.abs(vFrom.z)) {
            v1.set(-vFrom.y, vFrom.x, 0);
          } else {
            v1.set(0, -vFrom.z, vFrom.y);
          }
        } else {
          v1.crossVectors(vFrom, vTo);
        }
        this._x = v1.x;
        this._y = v1.y;
        this._z = v1.z;
        this._w = r;
        return this.normalize();
      };
    }(),
    inverse: function() {
      return this.conjugate().normalize();
    },
    conjugate: function() {
      this._x *= -1;
      this._y *= -1;
      this._z *= -1;
      this.onChangeCallback();
      return this;
    },
    dot: function(v) {
      return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w;
    },
    lengthSq: function() {
      return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w;
    },
    length: function() {
      return Math.sqrt(this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w);
    },
    normalize: function() {
      var l = this.length();
      if (l === 0) {
        this._x = 0;
        this._y = 0;
        this._z = 0;
        this._w = 1;
      } else {
        l = 1 / l;
        this._x = this._x * l;
        this._y = this._y * l;
        this._z = this._z * l;
        this._w = this._w * l;
      }
      this.onChangeCallback();
      return this;
    },
    multiply: function(q, p) {
      if (p !== undefined) {
        console.warn('THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead.');
        return this.multiplyQuaternions(q, p);
      }
      return this.multiplyQuaternions(this, q);
    },
    premultiply: function(q) {
      return this.multiplyQuaternions(q, this);
    },
    multiplyQuaternions: function(a, b) {
      var qax = a._x,
          qay = a._y,
          qaz = a._z,
          qaw = a._w;
      var qbx = b._x,
          qby = b._y,
          qbz = b._z,
          qbw = b._w;
      this._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby;
      this._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz;
      this._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx;
      this._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz;
      this.onChangeCallback();
      return this;
    },
    slerp: function(qb, t) {
      if (t === 0)
        return this;
      if (t === 1)
        return this.copy(qb);
      var x = this._x,
          y = this._y,
          z = this._z,
          w = this._w;
      var cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z;
      if (cosHalfTheta < 0) {
        this._w = -qb._w;
        this._x = -qb._x;
        this._y = -qb._y;
        this._z = -qb._z;
        cosHalfTheta = -cosHalfTheta;
      } else {
        this.copy(qb);
      }
      if (cosHalfTheta >= 1.0) {
        this._w = w;
        this._x = x;
        this._y = y;
        this._z = z;
        return this;
      }
      var sinHalfTheta = Math.sqrt(1.0 - cosHalfTheta * cosHalfTheta);
      if (Math.abs(sinHalfTheta) < 0.001) {
        this._w = 0.5 * (w + this._w);
        this._x = 0.5 * (x + this._x);
        this._y = 0.5 * (y + this._y);
        this._z = 0.5 * (z + this._z);
        return this;
      }
      var halfTheta = Math.atan2(sinHalfTheta, cosHalfTheta);
      var ratioA = Math.sin((1 - t) * halfTheta) / sinHalfTheta,
          ratioB = Math.sin(t * halfTheta) / sinHalfTheta;
      this._w = (w * ratioA + this._w * ratioB);
      this._x = (x * ratioA + this._x * ratioB);
      this._y = (y * ratioA + this._y * ratioB);
      this._z = (z * ratioA + this._z * ratioB);
      this.onChangeCallback();
      return this;
    },
    equals: function(quaternion) {
      return (quaternion._x === this._x) && (quaternion._y === this._y) && (quaternion._z === this._z) && (quaternion._w === this._w);
    },
    fromArray: function(array, offset) {
      if (offset === undefined)
        offset = 0;
      this._x = array[offset];
      this._y = array[offset + 1];
      this._z = array[offset + 2];
      this._w = array[offset + 3];
      this.onChangeCallback();
      return this;
    },
    toArray: function(array, offset) {
      if (array === undefined)
        array = [];
      if (offset === undefined)
        offset = 0;
      array[offset] = this._x;
      array[offset + 1] = this._y;
      array[offset + 2] = this._z;
      array[offset + 3] = this._w;
      return array;
    },
    onChange: function(callback) {
      this.onChangeCallback = callback;
      return this;
    },
    onChangeCallback: function() {}
  };
  Object.assign(THREE.Quaternion, {
    slerp: function(qa, qb, qm, t) {
      return qm.copy(qa).slerp(qb, t);
    },
    slerpFlat: function(dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t) {
      var x0 = src0[srcOffset0 + 0],
          y0 = src0[srcOffset0 + 1],
          z0 = src0[srcOffset0 + 2],
          w0 = src0[srcOffset0 + 3],
          x1 = src1[srcOffset1 + 0],
          y1 = src1[srcOffset1 + 1],
          z1 = src1[srcOffset1 + 2],
          w1 = src1[srcOffset1 + 3];
      if (w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1) {
        var s = 1 - t,
            cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1,
            dir = (cos >= 0 ? 1 : -1),
            sqrSin = 1 - cos * cos;
        if (sqrSin > Number.EPSILON) {
          var sin = Math.sqrt(sqrSin),
              len = Math.atan2(sin, cos * dir);
          s = Math.sin(s * len) / sin;
          t = Math.sin(t * len) / sin;
        }
        var tDir = t * dir;
        x0 = x0 * s + x1 * tDir;
        y0 = y0 * s + y1 * tDir;
        z0 = z0 * s + z1 * tDir;
        w0 = w0 * s + w1 * tDir;
        if (s === 1 - t) {
          var f = 1 / Math.sqrt(x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0);
          x0 *= f;
          y0 *= f;
          z0 *= f;
          w0 *= f;
        }
      }
      dst[dstOffset] = x0;
      dst[dstOffset + 1] = y0;
      dst[dstOffset + 2] = z0;
      dst[dstOffset + 3] = w0;
    }
  });
  THREE.Vector2 = function(x, y) {
    this.x = x || 0;
    this.y = y || 0;
  };
  THREE.Vector2.prototype = {
    constructor: THREE.Vector2,
    get width() {
      return this.x;
    },
    set width(value) {
      this.x = value;
    },
    get height() {
      return this.y;
    },
    set height(value) {
      this.y = value;
    },
    set: function(x, y) {
      this.x = x;
      this.y = y;
      return this;
    },
    setScalar: function(scalar) {
      this.x = scalar;
      this.y = scalar;
      return this;
    },
    setX: function(x) {
      this.x = x;
      return this;
    },
    setY: function(y) {
      this.y = y;
      return this;
    },
    setComponent: function(index, value) {
      switch (index) {
        case 0:
          this.x = value;
          break;
        case 1:
          this.y = value;
          break;
        default:
          throw new Error('index is out of range: ' + index);
      }
    },
    getComponent: function(index) {
      switch (index) {
        case 0:
          return this.x;
        case 1:
          return this.y;
        default:
          throw new Error('index is out of range: ' + index);
      }
    },
    clone: function() {
      return new this.constructor(this.x, this.y);
    },
    copy: function(v) {
      this.x = v.x;
      this.y = v.y;
      return this;
    },
    add: function(v, w) {
      if (w !== undefined) {
        console.warn('THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead.');
        return this.addVectors(v, w);
      }
      this.x += v.x;
      this.y += v.y;
      return this;
    },
    addScalar: function(s) {
      this.x += s;
      this.y += s;
      return this;
    },
    addVectors: function(a, b) {
      this.x = a.x + b.x;
      this.y = a.y + b.y;
      return this;
    },
    addScaledVector: function(v, s) {
      this.x += v.x * s;
      this.y += v.y * s;
      return this;
    },
    sub: function(v, w) {
      if (w !== undefined) {
        console.warn('THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.');
        return this.subVectors(v, w);
      }
      this.x -= v.x;
      this.y -= v.y;
      return this;
    },
    subScalar: function(s) {
      this.x -= s;
      this.y -= s;
      return this;
    },
    subVectors: function(a, b) {
      this.x = a.x - b.x;
      this.y = a.y - b.y;
      return this;
    },
    multiply: function(v) {
      this.x *= v.x;
      this.y *= v.y;
      return this;
    },
    multiplyScalar: function(scalar) {
      if (isFinite(scalar)) {
        this.x *= scalar;
        this.y *= scalar;
      } else {
        this.x = 0;
        this.y = 0;
      }
      return this;
    },
    divide: function(v) {
      this.x /= v.x;
      this.y /= v.y;
      return this;
    },
    divideScalar: function(scalar) {
      return this.multiplyScalar(1 / scalar);
    },
    min: function(v) {
      this.x = Math.min(this.x, v.x);
      this.y = Math.min(this.y, v.y);
      return this;
    },
    max: function(v) {
      this.x = Math.max(this.x, v.x);
      this.y = Math.max(this.y, v.y);
      return this;
    },
    clamp: function(min, max) {
      this.x = Math.max(min.x, Math.min(max.x, this.x));
      this.y = Math.max(min.y, Math.min(max.y, this.y));
      return this;
    },
    clampScalar: function() {
      var min,
          max;
      return function clampScalar(minVal, maxVal) {
        if (min === undefined) {
          min = new THREE.Vector2();
          max = new THREE.Vector2();
        }
        min.set(minVal, minVal);
        max.set(maxVal, maxVal);
        return this.clamp(min, max);
      };
    }(),
    clampLength: function(min, max) {
      var length = this.length();
      return this.multiplyScalar(Math.max(min, Math.min(max, length)) / length);
    },
    floor: function() {
      this.x = Math.floor(this.x);
      this.y = Math.floor(this.y);
      return this;
    },
    ceil: function() {
      this.x = Math.ceil(this.x);
      this.y = Math.ceil(this.y);
      return this;
    },
    round: function() {
      this.x = Math.round(this.x);
      this.y = Math.round(this.y);
      return this;
    },
    roundToZero: function() {
      this.x = (this.x < 0) ? Math.ceil(this.x) : Math.floor(this.x);
      this.y = (this.y < 0) ? Math.ceil(this.y) : Math.floor(this.y);
      return this;
    },
    negate: function() {
      this.x = -this.x;
      this.y = -this.y;
      return this;
    },
    dot: function(v) {
      return this.x * v.x + this.y * v.y;
    },
    lengthSq: function() {
      return this.x * this.x + this.y * this.y;
    },
    length: function() {
      return Math.sqrt(this.x * this.x + this.y * this.y);
    },
    lengthManhattan: function() {
      return Math.abs(this.x) + Math.abs(this.y);
    },
    normalize: function() {
      return this.divideScalar(this.length());
    },
    angle: function() {
      var angle = Math.atan2(this.y, this.x);
      if (angle < 0)
        angle += 2 * Math.PI;
      return angle;
    },
    distanceTo: function(v) {
      return Math.sqrt(this.distanceToSquared(v));
    },
    distanceToSquared: function(v) {
      var dx = this.x - v.x,
          dy = this.y - v.y;
      return dx * dx + dy * dy;
    },
    setLength: function(length) {
      return this.multiplyScalar(length / this.length());
    },
    lerp: function(v, alpha) {
      this.x += (v.x - this.x) * alpha;
      this.y += (v.y - this.y) * alpha;
      return this;
    },
    lerpVectors: function(v1, v2, alpha) {
      return this.subVectors(v2, v1).multiplyScalar(alpha).add(v1);
    },
    equals: function(v) {
      return ((v.x === this.x) && (v.y === this.y));
    },
    fromArray: function(array, offset) {
      if (offset === undefined)
        offset = 0;
      this.x = array[offset];
      this.y = array[offset + 1];
      return this;
    },
    toArray: function(array, offset) {
      if (array === undefined)
        array = [];
      if (offset === undefined)
        offset = 0;
      array[offset] = this.x;
      array[offset + 1] = this.y;
      return array;
    },
    fromAttribute: function(attribute, index, offset) {
      if (offset === undefined)
        offset = 0;
      index = index * attribute.itemSize + offset;
      this.x = attribute.array[index];
      this.y = attribute.array[index + 1];
      return this;
    },
    rotateAround: function(center, angle) {
      var c = Math.cos(angle),
          s = Math.sin(angle);
      var x = this.x - center.x;
      var y = this.y - center.y;
      this.x = x * c - y * s + center.x;
      this.y = x * s + y * c + center.y;
      return this;
    }
  };
  THREE.Vector3 = function(x, y, z) {
    this.x = x || 0;
    this.y = y || 0;
    this.z = z || 0;
  };
  THREE.Vector3.prototype = {
    constructor: THREE.Vector3,
    set: function(x, y, z) {
      this.x = x;
      this.y = y;
      this.z = z;
      return this;
    },
    setScalar: function(scalar) {
      this.x = scalar;
      this.y = scalar;
      this.z = scalar;
      return this;
    },
    setX: function(x) {
      this.x = x;
      return this;
    },
    setY: function(y) {
      this.y = y;
      return this;
    },
    setZ: function(z) {
      this.z = z;
      return this;
    },
    setComponent: function(index, value) {
      switch (index) {
        case 0:
          this.x = value;
          break;
        case 1:
          this.y = value;
          break;
        case 2:
          this.z = value;
          break;
        default:
          throw new Error('index is out of range: ' + index);
      }
    },
    getComponent: function(index) {
      switch (index) {
        case 0:
          return this.x;
        case 1:
          return this.y;
        case 2:
          return this.z;
        default:
          throw new Error('index is out of range: ' + index);
      }
    },
    clone: function() {
      return new this.constructor(this.x, this.y, this.z);
    },
    copy: function(v) {
      this.x = v.x;
      this.y = v.y;
      this.z = v.z;
      return this;
    },
    add: function(v, w) {
      if (w !== undefined) {
        console.warn('THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead.');
        return this.addVectors(v, w);
      }
      this.x += v.x;
      this.y += v.y;
      this.z += v.z;
      return this;
    },
    addScalar: function(s) {
      this.x += s;
      this.y += s;
      this.z += s;
      return this;
    },
    addVectors: function(a, b) {
      this.x = a.x + b.x;
      this.y = a.y + b.y;
      this.z = a.z + b.z;
      return this;
    },
    addScaledVector: function(v, s) {
      this.x += v.x * s;
      this.y += v.y * s;
      this.z += v.z * s;
      return this;
    },
    sub: function(v, w) {
      if (w !== undefined) {
        console.warn('THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.');
        return this.subVectors(v, w);
      }
      this.x -= v.x;
      this.y -= v.y;
      this.z -= v.z;
      return this;
    },
    subScalar: function(s) {
      this.x -= s;
      this.y -= s;
      this.z -= s;
      return this;
    },
    subVectors: function(a, b) {
      this.x = a.x - b.x;
      this.y = a.y - b.y;
      this.z = a.z - b.z;
      return this;
    },
    multiply: function(v, w) {
      if (w !== undefined) {
        console.warn('THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead.');
        return this.multiplyVectors(v, w);
      }
      this.x *= v.x;
      this.y *= v.y;
      this.z *= v.z;
      return this;
    },
    multiplyScalar: function(scalar) {
      if (isFinite(scalar)) {
        this.x *= scalar;
        this.y *= scalar;
        this.z *= scalar;
      } else {
        this.x = 0;
        this.y = 0;
        this.z = 0;
      }
      return this;
    },
    multiplyVectors: function(a, b) {
      this.x = a.x * b.x;
      this.y = a.y * b.y;
      this.z = a.z * b.z;
      return this;
    },
    applyEuler: function() {
      var quaternion;
      return function applyEuler(euler) {
        if (euler instanceof THREE.Euler === false) {
          console.error('THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order.');
        }
        if (quaternion === undefined)
          quaternion = new THREE.Quaternion();
        return this.applyQuaternion(quaternion.setFromEuler(euler));
      };
    }(),
    applyAxisAngle: function() {
      var quaternion;
      return function applyAxisAngle(axis, angle) {
        if (quaternion === undefined)
          quaternion = new THREE.Quaternion();
        return this.applyQuaternion(quaternion.setFromAxisAngle(axis, angle));
      };
    }(),
    applyMatrix3: function(m) {
      var x = this.x,
          y = this.y,
          z = this.z;
      var e = m.elements;
      this.x = e[0] * x + e[3] * y + e[6] * z;
      this.y = e[1] * x + e[4] * y + e[7] * z;
      this.z = e[2] * x + e[5] * y + e[8] * z;
      return this;
    },
    applyMatrix4: function(m) {
      var x = this.x,
          y = this.y,
          z = this.z;
      var e = m.elements;
      this.x = e[0] * x + e[4] * y + e[8] * z + e[12];
      this.y = e[1] * x + e[5] * y + e[9] * z + e[13];
      this.z = e[2] * x + e[6] * y + e[10] * z + e[14];
      return this;
    },
    applyProjection: function(m) {
      var x = this.x,
          y = this.y,
          z = this.z;
      var e = m.elements;
      var d = 1 / (e[3] * x + e[7] * y + e[11] * z + e[15]);
      this.x = (e[0] * x + e[4] * y + e[8] * z + e[12]) * d;
      this.y = (e[1] * x + e[5] * y + e[9] * z + e[13]) * d;
      this.z = (e[2] * x + e[6] * y + e[10] * z + e[14]) * d;
      return this;
    },
    applyQuaternion: function(q) {
      var x = this.x,
          y = this.y,
          z = this.z;
      var qx = q.x,
          qy = q.y,
          qz = q.z,
          qw = q.w;
      var ix = qw * x + qy * z - qz * y;
      var iy = qw * y + qz * x - qx * z;
      var iz = qw * z + qx * y - qy * x;
      var iw = -qx * x - qy * y - qz * z;
      this.x = ix * qw + iw * -qx + iy * -qz - iz * -qy;
      this.y = iy * qw + iw * -qy + iz * -qx - ix * -qz;
      this.z = iz * qw + iw * -qz + ix * -qy - iy * -qx;
      return this;
    },
    project: function() {
      var matrix;
      return function project(camera) {
        if (matrix === undefined)
          matrix = new THREE.Matrix4();
        matrix.multiplyMatrices(camera.projectionMatrix, matrix.getInverse(camera.matrixWorld));
        return this.applyProjection(matrix);
      };
    }(),
    unproject: function() {
      var matrix;
      return function unproject(camera) {
        if (matrix === undefined)
          matrix = new THREE.Matrix4();
        matrix.multiplyMatrices(camera.matrixWorld, matrix.getInverse(camera.projectionMatrix));
        return this.applyProjection(matrix);
      };
    }(),
    transformDirection: function(m) {
      var x = this.x,
          y = this.y,
          z = this.z;
      var e = m.elements;
      this.x = e[0] * x + e[4] * y + e[8] * z;
      this.y = e[1] * x + e[5] * y + e[9] * z;
      this.z = e[2] * x + e[6] * y + e[10] * z;
      return this.normalize();
    },
    divide: function(v) {
      this.x /= v.x;
      this.y /= v.y;
      this.z /= v.z;
      return this;
    },
    divideScalar: function(scalar) {
      return this.multiplyScalar(1 / scalar);
    },
    min: function(v) {
      this.x = Math.min(this.x, v.x);
      this.y = Math.min(this.y, v.y);
      this.z = Math.min(this.z, v.z);
      return this;
    },
    max: function(v) {
      this.x = Math.max(this.x, v.x);
      this.y = Math.max(this.y, v.y);
      this.z = Math.max(this.z, v.z);
      return this;
    },
    clamp: function(min, max) {
      this.x = Math.max(min.x, Math.min(max.x, this.x));
      this.y = Math.max(min.y, Math.min(max.y, this.y));
      this.z = Math.max(min.z, Math.min(max.z, this.z));
      return this;
    },
    clampScalar: function() {
      var min,
          max;
      return function clampScalar(minVal, maxVal) {
        if (min === undefined) {
          min = new THREE.Vector3();
          max = new THREE.Vector3();
        }
        min.set(minVal, minVal, minVal);
        max.set(maxVal, maxVal, maxVal);
        return this.clamp(min, max);
      };
    }(),
    clampLength: function(min, max) {
      var length = this.length();
      return this.multiplyScalar(Math.max(min, Math.min(max, length)) / length);
    },
    floor: function() {
      this.x = Math.floor(this.x);
      this.y = Math.floor(this.y);
      this.z = Math.floor(this.z);
      return this;
    },
    ceil: function() {
      this.x = Math.ceil(this.x);
      this.y = Math.ceil(this.y);
      this.z = Math.ceil(this.z);
      return this;
    },
    round: function() {
      this.x = Math.round(this.x);
      this.y = Math.round(this.y);
      this.z = Math.round(this.z);
      return this;
    },
    roundToZero: function() {
      this.x = (this.x < 0) ? Math.ceil(this.x) : Math.floor(this.x);
      this.y = (this.y < 0) ? Math.ceil(this.y) : Math.floor(this.y);
      this.z = (this.z < 0) ? Math.ceil(this.z) : Math.floor(this.z);
      return this;
    },
    negate: function() {
      this.x = -this.x;
      this.y = -this.y;
      this.z = -this.z;
      return this;
    },
    dot: function(v) {
      return this.x * v.x + this.y * v.y + this.z * v.z;
    },
    lengthSq: function() {
      return this.x * this.x + this.y * this.y + this.z * this.z;
    },
    length: function() {
      return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
    },
    lengthManhattan: function() {
      return Math.abs(this.x) + Math.abs(this.y) + Math.abs(this.z);
    },
    normalize: function() {
      return this.divideScalar(this.length());
    },
    setLength: function(length) {
      return this.multiplyScalar(length / this.length());
    },
    lerp: function(v, alpha) {
      this.x += (v.x - this.x) * alpha;
      this.y += (v.y - this.y) * alpha;
      this.z += (v.z - this.z) * alpha;
      return this;
    },
    lerpVectors: function(v1, v2, alpha) {
      return this.subVectors(v2, v1).multiplyScalar(alpha).add(v1);
    },
    cross: function(v, w) {
      if (w !== undefined) {
        console.warn('THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead.');
        return this.crossVectors(v, w);
      }
      var x = this.x,
          y = this.y,
          z = this.z;
      this.x = y * v.z - z * v.y;
      this.y = z * v.x - x * v.z;
      this.z = x * v.y - y * v.x;
      return this;
    },
    crossVectors: function(a, b) {
      var ax = a.x,
          ay = a.y,
          az = a.z;
      var bx = b.x,
          by = b.y,
          bz = b.z;
      this.x = ay * bz - az * by;
      this.y = az * bx - ax * bz;
      this.z = ax * by - ay * bx;
      return this;
    },
    projectOnVector: function(vector) {
      var scalar = vector.dot(this) / vector.lengthSq();
      return this.copy(vector).multiplyScalar(scalar);
    },
    projectOnPlane: function() {
      var v1;
      return function projectOnPlane(planeNormal) {
        if (v1 === undefined)
          v1 = new THREE.Vector3();
        v1.copy(this).projectOnVector(planeNormal);
        return this.sub(v1);
      };
    }(),
    reflect: function() {
      var v1;
      return function reflect(normal) {
        if (v1 === undefined)
          v1 = new THREE.Vector3();
        return this.sub(v1.copy(normal).multiplyScalar(2 * this.dot(normal)));
      };
    }(),
    angleTo: function(v) {
      var theta = this.dot(v) / (Math.sqrt(this.lengthSq() * v.lengthSq()));
      return Math.acos(THREE.Math.clamp(theta, -1, 1));
    },
    distanceTo: function(v) {
      return Math.sqrt(this.distanceToSquared(v));
    },
    distanceToSquared: function(v) {
      var dx = this.x - v.x,
          dy = this.y - v.y,
          dz = this.z - v.z;
      return dx * dx + dy * dy + dz * dz;
    },
    setFromSpherical: function(s) {
      var sinPhiRadius = Math.sin(s.phi) * s.radius;
      this.x = sinPhiRadius * Math.sin(s.theta);
      this.y = Math.cos(s.phi) * s.radius;
      this.z = sinPhiRadius * Math.cos(s.theta);
      return this;
    },
    setFromMatrixPosition: function(m) {
      return this.setFromMatrixColumn(m, 3);
    },
    setFromMatrixScale: function(m) {
      var sx = this.setFromMatrixColumn(m, 0).length();
      var sy = this.setFromMatrixColumn(m, 1).length();
      var sz = this.setFromMatrixColumn(m, 2).length();
      this.x = sx;
      this.y = sy;
      this.z = sz;
      return this;
    },
    setFromMatrixColumn: function(m, index) {
      if (typeof m === 'number') {
        console.warn('THREE.Vector3: setFromMatrixColumn now expects ( matrix, index ).');
        var temp = m;
        m = index;
        index = temp;
      }
      return this.fromArray(m.elements, index * 4);
    },
    equals: function(v) {
      return ((v.x === this.x) && (v.y === this.y) && (v.z === this.z));
    },
    fromArray: function(array, offset) {
      if (offset === undefined)
        offset = 0;
      this.x = array[offset];
      this.y = array[offset + 1];
      this.z = array[offset + 2];
      return this;
    },
    toArray: function(array, offset) {
      if (array === undefined)
        array = [];
      if (offset === undefined)
        offset = 0;
      array[offset] = this.x;
      array[offset + 1] = this.y;
      array[offset + 2] = this.z;
      return array;
    },
    fromAttribute: function(attribute, index, offset) {
      if (offset === undefined)
        offset = 0;
      index = index * attribute.itemSize + offset;
      this.x = attribute.array[index];
      this.y = attribute.array[index + 1];
      this.z = attribute.array[index + 2];
      return this;
    }
  };
  THREE.Vector4 = function(x, y, z, w) {
    this.x = x || 0;
    this.y = y || 0;
    this.z = z || 0;
    this.w = (w !== undefined) ? w : 1;
  };
  THREE.Vector4.prototype = {
    constructor: THREE.Vector4,
    set: function(x, y, z, w) {
      this.x = x;
      this.y = y;
      this.z = z;
      this.w = w;
      return this;
    },
    setScalar: function(scalar) {
      this.x = scalar;
      this.y = scalar;
      this.z = scalar;
      this.w = scalar;
      return this;
    },
    setX: function(x) {
      this.x = x;
      return this;
    },
    setY: function(y) {
      this.y = y;
      return this;
    },
    setZ: function(z) {
      this.z = z;
      return this;
    },
    setW: function(w) {
      this.w = w;
      return this;
    },
    setComponent: function(index, value) {
      switch (index) {
        case 0:
          this.x = value;
          break;
        case 1:
          this.y = value;
          break;
        case 2:
          this.z = value;
          break;
        case 3:
          this.w = value;
          break;
        default:
          throw new Error('index is out of range: ' + index);
      }
    },
    getComponent: function(index) {
      switch (index) {
        case 0:
          return this.x;
        case 1:
          return this.y;
        case 2:
          return this.z;
        case 3:
          return this.w;
        default:
          throw new Error('index is out of range: ' + index);
      }
    },
    clone: function() {
      return new this.constructor(this.x, this.y, this.z, this.w);
    },
    copy: function(v) {
      this.x = v.x;
      this.y = v.y;
      this.z = v.z;
      this.w = (v.w !== undefined) ? v.w : 1;
      return this;
    },
    add: function(v, w) {
      if (w !== undefined) {
        console.warn('THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead.');
        return this.addVectors(v, w);
      }
      this.x += v.x;
      this.y += v.y;
      this.z += v.z;
      this.w += v.w;
      return this;
    },
    addScalar: function(s) {
      this.x += s;
      this.y += s;
      this.z += s;
      this.w += s;
      return this;
    },
    addVectors: function(a, b) {
      this.x = a.x + b.x;
      this.y = a.y + b.y;
      this.z = a.z + b.z;
      this.w = a.w + b.w;
      return this;
    },
    addScaledVector: function(v, s) {
      this.x += v.x * s;
      this.y += v.y * s;
      this.z += v.z * s;
      this.w += v.w * s;
      return this;
    },
    sub: function(v, w) {
      if (w !== undefined) {
        console.warn('THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.');
        return this.subVectors(v, w);
      }
      this.x -= v.x;
      this.y -= v.y;
      this.z -= v.z;
      this.w -= v.w;
      return this;
    },
    subScalar: function(s) {
      this.x -= s;
      this.y -= s;
      this.z -= s;
      this.w -= s;
      return this;
    },
    subVectors: function(a, b) {
      this.x = a.x - b.x;
      this.y = a.y - b.y;
      this.z = a.z - b.z;
      this.w = a.w - b.w;
      return this;
    },
    multiplyScalar: function(scalar) {
      if (isFinite(scalar)) {
        this.x *= scalar;
        this.y *= scalar;
        this.z *= scalar;
        this.w *= scalar;
      } else {
        this.x = 0;
        this.y = 0;
        this.z = 0;
        this.w = 0;
      }
      return this;
    },
    applyMatrix4: function(m) {
      var x = this.x,
          y = this.y,
          z = this.z,
          w = this.w;
      var e = m.elements;
      this.x = e[0] * x + e[4] * y + e[8] * z + e[12] * w;
      this.y = e[1] * x + e[5] * y + e[9] * z + e[13] * w;
      this.z = e[2] * x + e[6] * y + e[10] * z + e[14] * w;
      this.w = e[3] * x + e[7] * y + e[11] * z + e[15] * w;
      return this;
    },
    divideScalar: function(scalar) {
      return this.multiplyScalar(1 / scalar);
    },
    setAxisAngleFromQuaternion: function(q) {
      this.w = 2 * Math.acos(q.w);
      var s = Math.sqrt(1 - q.w * q.w);
      if (s < 0.0001) {
        this.x = 1;
        this.y = 0;
        this.z = 0;
      } else {
        this.x = q.x / s;
        this.y = q.y / s;
        this.z = q.z / s;
      }
      return this;
    },
    setAxisAngleFromRotationMatrix: function(m) {
      var angle,
          x,
          y,
          z,
          epsilon = 0.01,
          epsilon2 = 0.1,
          te = m.elements,
          m11 = te[0],
          m12 = te[4],
          m13 = te[8],
          m21 = te[1],
          m22 = te[5],
          m23 = te[9],
          m31 = te[2],
          m32 = te[6],
          m33 = te[10];
      if ((Math.abs(m12 - m21) < epsilon) && (Math.abs(m13 - m31) < epsilon) && (Math.abs(m23 - m32) < epsilon)) {
        if ((Math.abs(m12 + m21) < epsilon2) && (Math.abs(m13 + m31) < epsilon2) && (Math.abs(m23 + m32) < epsilon2) && (Math.abs(m11 + m22 + m33 - 3) < epsilon2)) {
          this.set(1, 0, 0, 0);
          return this;
        }
        angle = Math.PI;
        var xx = (m11 + 1) / 2;
        var yy = (m22 + 1) / 2;
        var zz = (m33 + 1) / 2;
        var xy = (m12 + m21) / 4;
        var xz = (m13 + m31) / 4;
        var yz = (m23 + m32) / 4;
        if ((xx > yy) && (xx > zz)) {
          if (xx < epsilon) {
            x = 0;
            y = 0.707106781;
            z = 0.707106781;
          } else {
            x = Math.sqrt(xx);
            y = xy / x;
            z = xz / x;
          }
        } else if (yy > zz) {
          if (yy < epsilon) {
            x = 0.707106781;
            y = 0;
            z = 0.707106781;
          } else {
            y = Math.sqrt(yy);
            x = xy / y;
            z = yz / y;
          }
        } else {
          if (zz < epsilon) {
            x = 0.707106781;
            y = 0.707106781;
            z = 0;
          } else {
            z = Math.sqrt(zz);
            x = xz / z;
            y = yz / z;
          }
        }
        this.set(x, y, z, angle);
        return this;
      }
      var s = Math.sqrt((m32 - m23) * (m32 - m23) + (m13 - m31) * (m13 - m31) + (m21 - m12) * (m21 - m12));
      if (Math.abs(s) < 0.001)
        s = 1;
      this.x = (m32 - m23) / s;
      this.y = (m13 - m31) / s;
      this.z = (m21 - m12) / s;
      this.w = Math.acos((m11 + m22 + m33 - 1) / 2);
      return this;
    },
    min: function(v) {
      this.x = Math.min(this.x, v.x);
      this.y = Math.min(this.y, v.y);
      this.z = Math.min(this.z, v.z);
      this.w = Math.min(this.w, v.w);
      return this;
    },
    max: function(v) {
      this.x = Math.max(this.x, v.x);
      this.y = Math.max(this.y, v.y);
      this.z = Math.max(this.z, v.z);
      this.w = Math.max(this.w, v.w);
      return this;
    },
    clamp: function(min, max) {
      this.x = Math.max(min.x, Math.min(max.x, this.x));
      this.y = Math.max(min.y, Math.min(max.y, this.y));
      this.z = Math.max(min.z, Math.min(max.z, this.z));
      this.w = Math.max(min.w, Math.min(max.w, this.w));
      return this;
    },
    clampScalar: function() {
      var min,
          max;
      return function clampScalar(minVal, maxVal) {
        if (min === undefined) {
          min = new THREE.Vector4();
          max = new THREE.Vector4();
        }
        min.set(minVal, minVal, minVal, minVal);
        max.set(maxVal, maxVal, maxVal, maxVal);
        return this.clamp(min, max);
      };
    }(),
    floor: function() {
      this.x = Math.floor(this.x);
      this.y = Math.floor(this.y);
      this.z = Math.floor(this.z);
      this.w = Math.floor(this.w);
      return this;
    },
    ceil: function() {
      this.x = Math.ceil(this.x);
      this.y = Math.ceil(this.y);
      this.z = Math.ceil(this.z);
      this.w = Math.ceil(this.w);
      return this;
    },
    round: function() {
      this.x = Math.round(this.x);
      this.y = Math.round(this.y);
      this.z = Math.round(this.z);
      this.w = Math.round(this.w);
      return this;
    },
    roundToZero: function() {
      this.x = (this.x < 0) ? Math.ceil(this.x) : Math.floor(this.x);
      this.y = (this.y < 0) ? Math.ceil(this.y) : Math.floor(this.y);
      this.z = (this.z < 0) ? Math.ceil(this.z) : Math.floor(this.z);
      this.w = (this.w < 0) ? Math.ceil(this.w) : Math.floor(this.w);
      return this;
    },
    negate: function() {
      this.x = -this.x;
      this.y = -this.y;
      this.z = -this.z;
      this.w = -this.w;
      return this;
    },
    dot: function(v) {
      return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w;
    },
    lengthSq: function() {
      return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;
    },
    length: function() {
      return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w);
    },
    lengthManhattan: function() {
      return Math.abs(this.x) + Math.abs(this.y) + Math.abs(this.z) + Math.abs(this.w);
    },
    normalize: function() {
      return this.divideScalar(this.length());
    },
    setLength: function(length) {
      return this.multiplyScalar(length / this.length());
    },
    lerp: function(v, alpha) {
      this.x += (v.x - this.x) * alpha;
      this.y += (v.y - this.y) * alpha;
      this.z += (v.z - this.z) * alpha;
      this.w += (v.w - this.w) * alpha;
      return this;
    },
    lerpVectors: function(v1, v2, alpha) {
      return this.subVectors(v2, v1).multiplyScalar(alpha).add(v1);
    },
    equals: function(v) {
      return ((v.x === this.x) && (v.y === this.y) && (v.z === this.z) && (v.w === this.w));
    },
    fromArray: function(array, offset) {
      if (offset === undefined)
        offset = 0;
      this.x = array[offset];
      this.y = array[offset + 1];
      this.z = array[offset + 2];
      this.w = array[offset + 3];
      return this;
    },
    toArray: function(array, offset) {
      if (array === undefined)
        array = [];
      if (offset === undefined)
        offset = 0;
      array[offset] = this.x;
      array[offset + 1] = this.y;
      array[offset + 2] = this.z;
      array[offset + 3] = this.w;
      return array;
    },
    fromAttribute: function(attribute, index, offset) {
      if (offset === undefined)
        offset = 0;
      index = index * attribute.itemSize + offset;
      this.x = attribute.array[index];
      this.y = attribute.array[index + 1];
      this.z = attribute.array[index + 2];
      this.w = attribute.array[index + 3];
      return this;
    }
  };
  THREE.Euler = function(x, y, z, order) {
    this._x = x || 0;
    this._y = y || 0;
    this._z = z || 0;
    this._order = order || THREE.Euler.DefaultOrder;
  };
  THREE.Euler.RotationOrders = ['XYZ', 'YZX', 'ZXY', 'XZY', 'YXZ', 'ZYX'];
  THREE.Euler.DefaultOrder = 'XYZ';
  THREE.Euler.prototype = {
    constructor: THREE.Euler,
    get x() {
      return this._x;
    },
    set x(value) {
      this._x = value;
      this.onChangeCallback();
    },
    get y() {
      return this._y;
    },
    set y(value) {
      this._y = value;
      this.onChangeCallback();
    },
    get z() {
      return this._z;
    },
    set z(value) {
      this._z = value;
      this.onChangeCallback();
    },
    get order() {
      return this._order;
    },
    set order(value) {
      this._order = value;
      this.onChangeCallback();
    },
    set: function(x, y, z, order) {
      this._x = x;
      this._y = y;
      this._z = z;
      this._order = order || this._order;
      this.onChangeCallback();
      return this;
    },
    clone: function() {
      return new this.constructor(this._x, this._y, this._z, this._order);
    },
    copy: function(euler) {
      this._x = euler._x;
      this._y = euler._y;
      this._z = euler._z;
      this._order = euler._order;
      this.onChangeCallback();
      return this;
    },
    setFromRotationMatrix: function(m, order, update) {
      var clamp = THREE.Math.clamp;
      var te = m.elements;
      var m11 = te[0],
          m12 = te[4],
          m13 = te[8];
      var m21 = te[1],
          m22 = te[5],
          m23 = te[9];
      var m31 = te[2],
          m32 = te[6],
          m33 = te[10];
      order = order || this._order;
      if (order === 'XYZ') {
        this._y = Math.asin(clamp(m13, -1, 1));
        if (Math.abs(m13) < 0.99999) {
          this._x = Math.atan2(-m23, m33);
          this._z = Math.atan2(-m12, m11);
        } else {
          this._x = Math.atan2(m32, m22);
          this._z = 0;
        }
      } else if (order === 'YXZ') {
        this._x = Math.asin(-clamp(m23, -1, 1));
        if (Math.abs(m23) < 0.99999) {
          this._y = Math.atan2(m13, m33);
          this._z = Math.atan2(m21, m22);
        } else {
          this._y = Math.atan2(-m31, m11);
          this._z = 0;
        }
      } else if (order === 'ZXY') {
        this._x = Math.asin(clamp(m32, -1, 1));
        if (Math.abs(m32) < 0.99999) {
          this._y = Math.atan2(-m31, m33);
          this._z = Math.atan2(-m12, m22);
        } else {
          this._y = 0;
          this._z = Math.atan2(m21, m11);
        }
      } else if (order === 'ZYX') {
        this._y = Math.asin(-clamp(m31, -1, 1));
        if (Math.abs(m31) < 0.99999) {
          this._x = Math.atan2(m32, m33);
          this._z = Math.atan2(m21, m11);
        } else {
          this._x = 0;
          this._z = Math.atan2(-m12, m22);
        }
      } else if (order === 'YZX') {
        this._z = Math.asin(clamp(m21, -1, 1));
        if (Math.abs(m21) < 0.99999) {
          this._x = Math.atan2(-m23, m22);
          this._y = Math.atan2(-m31, m11);
        } else {
          this._x = 0;
          this._y = Math.atan2(m13, m33);
        }
      } else if (order === 'XZY') {
        this._z = Math.asin(-clamp(m12, -1, 1));
        if (Math.abs(m12) < 0.99999) {
          this._x = Math.atan2(m32, m22);
          this._y = Math.atan2(m13, m11);
        } else {
          this._x = Math.atan2(-m23, m33);
          this._y = 0;
        }
      } else {
        console.warn('THREE.Euler: .setFromRotationMatrix() given unsupported order: ' + order);
      }
      this._order = order;
      if (update !== false)
        this.onChangeCallback();
      return this;
    },
    setFromQuaternion: function() {
      var matrix;
      return function setFromQuaternion(q, order, update) {
        if (matrix === undefined)
          matrix = new THREE.Matrix4();
        matrix.makeRotationFromQuaternion(q);
        return this.setFromRotationMatrix(matrix, order, update);
      };
    }(),
    setFromVector3: function(v, order) {
      return this.set(v.x, v.y, v.z, order || this._order);
    },
    reorder: function() {
      var q = new THREE.Quaternion();
      return function reorder(newOrder) {
        q.setFromEuler(this);
        return this.setFromQuaternion(q, newOrder);
      };
    }(),
    equals: function(euler) {
      return (euler._x === this._x) && (euler._y === this._y) && (euler._z === this._z) && (euler._order === this._order);
    },
    fromArray: function(array) {
      this._x = array[0];
      this._y = array[1];
      this._z = array[2];
      if (array[3] !== undefined)
        this._order = array[3];
      this.onChangeCallback();
      return this;
    },
    toArray: function(array, offset) {
      if (array === undefined)
        array = [];
      if (offset === undefined)
        offset = 0;
      array[offset] = this._x;
      array[offset + 1] = this._y;
      array[offset + 2] = this._z;
      array[offset + 3] = this._order;
      return array;
    },
    toVector3: function(optionalResult) {
      if (optionalResult) {
        return optionalResult.set(this._x, this._y, this._z);
      } else {
        return new THREE.Vector3(this._x, this._y, this._z);
      }
    },
    onChange: function(callback) {
      this.onChangeCallback = callback;
      return this;
    },
    onChangeCallback: function() {}
  };
  THREE.Line3 = function(start, end) {
    this.start = (start !== undefined) ? start : new THREE.Vector3();
    this.end = (end !== undefined) ? end : new THREE.Vector3();
  };
  THREE.Line3.prototype = {
    constructor: THREE.Line3,
    set: function(start, end) {
      this.start.copy(start);
      this.end.copy(end);
      return this;
    },
    clone: function() {
      return new this.constructor().copy(this);
    },
    copy: function(line) {
      this.start.copy(line.start);
      this.end.copy(line.end);
      return this;
    },
    center: function(optionalTarget) {
      var result = optionalTarget || new THREE.Vector3();
      return result.addVectors(this.start, this.end).multiplyScalar(0.5);
    },
    delta: function(optionalTarget) {
      var result = optionalTarget || new THREE.Vector3();
      return result.subVectors(this.end, this.start);
    },
    distanceSq: function() {
      return this.start.distanceToSquared(this.end);
    },
    distance: function() {
      return this.start.distanceTo(this.end);
    },
    at: function(t, optionalTarget) {
      var result = optionalTarget || new THREE.Vector3();
      return this.delta(result).multiplyScalar(t).add(this.start);
    },
    closestPointToPointParameter: function() {
      var startP = new THREE.Vector3();
      var startEnd = new THREE.Vector3();
      return function closestPointToPointParameter(point, clampToLine) {
        startP.subVectors(point, this.start);
        startEnd.subVectors(this.end, this.start);
        var startEnd2 = startEnd.dot(startEnd);
        var startEnd_startP = startEnd.dot(startP);
        var t = startEnd_startP / startEnd2;
        if (clampToLine) {
          t = THREE.Math.clamp(t, 0, 1);
        }
        return t;
      };
    }(),
    closestPointToPoint: function(point, clampToLine, optionalTarget) {
      var t = this.closestPointToPointParameter(point, clampToLine);
      var result = optionalTarget || new THREE.Vector3();
      return this.delta(result).multiplyScalar(t).add(this.start);
    },
    applyMatrix4: function(matrix) {
      this.start.applyMatrix4(matrix);
      this.end.applyMatrix4(matrix);
      return this;
    },
    equals: function(line) {
      return line.start.equals(this.start) && line.end.equals(this.end);
    }
  };
  THREE.Box2 = function(min, max) {
    this.min = (min !== undefined) ? min : new THREE.Vector2(+Infinity, +Infinity);
    this.max = (max !== undefined) ? max : new THREE.Vector2(-Infinity, -Infinity);
  };
  THREE.Box2.prototype = {
    constructor: THREE.Box2,
    set: function(min, max) {
      this.min.copy(min);
      this.max.copy(max);
      return this;
    },
    setFromPoints: function(points) {
      this.makeEmpty();
      for (var i = 0,
          il = points.length; i < il; i++) {
        this.expandByPoint(points[i]);
      }
      return this;
    },
    setFromCenterAndSize: function() {
      var v1 = new THREE.Vector2();
      return function setFromCenterAndSize(center, size) {
        var halfSize = v1.copy(size).multiplyScalar(0.5);
        this.min.copy(center).sub(halfSize);
        this.max.copy(center).add(halfSize);
        return this;
      };
    }(),
    clone: function() {
      return new this.constructor().copy(this);
    },
    copy: function(box) {
      this.min.copy(box.min);
      this.max.copy(box.max);
      return this;
    },
    makeEmpty: function() {
      this.min.x = this.min.y = +Infinity;
      this.max.x = this.max.y = -Infinity;
      return this;
    },
    isEmpty: function() {
      return (this.max.x < this.min.x) || (this.max.y < this.min.y);
    },
    center: function(optionalTarget) {
      var result = optionalTarget || new THREE.Vector2();
      return result.addVectors(this.min, this.max).multiplyScalar(0.5);
    },
    size: function(optionalTarget) {
      var result = optionalTarget || new THREE.Vector2();
      return result.subVectors(this.max, this.min);
    },
    expandByPoint: function(point) {
      this.min.min(point);
      this.max.max(point);
      return this;
    },
    expandByVector: function(vector) {
      this.min.sub(vector);
      this.max.add(vector);
      return this;
    },
    expandByScalar: function(scalar) {
      this.min.addScalar(-scalar);
      this.max.addScalar(scalar);
      return this;
    },
    containsPoint: function(point) {
      if (point.x < this.min.x || point.x > this.max.x || point.y < this.min.y || point.y > this.max.y) {
        return false;
      }
      return true;
    },
    containsBox: function(box) {
      if ((this.min.x <= box.min.x) && (box.max.x <= this.max.x) && (this.min.y <= box.min.y) && (box.max.y <= this.max.y)) {
        return true;
      }
      return false;
    },
    getParameter: function(point, optionalTarget) {
      var result = optionalTarget || new THREE.Vector2();
      return result.set((point.x - this.min.x) / (this.max.x - this.min.x), (point.y - this.min.y) / (this.max.y - this.min.y));
    },
    intersectsBox: function(box) {
      if (box.max.x < this.min.x || box.min.x > this.max.x || box.max.y < this.min.y || box.min.y > this.max.y) {
        return false;
      }
      return true;
    },
    clampPoint: function(point, optionalTarget) {
      var result = optionalTarget || new THREE.Vector2();
      return result.copy(point).clamp(this.min, this.max);
    },
    distanceToPoint: function() {
      var v1 = new THREE.Vector2();
      return function distanceToPoint(point) {
        var clampedPoint = v1.copy(point).clamp(this.min, this.max);
        return clampedPoint.sub(point).length();
      };
    }(),
    intersect: function(box) {
      this.min.max(box.min);
      this.max.min(box.max);
      return this;
    },
    union: function(box) {
      this.min.min(box.min);
      this.max.max(box.max);
      return this;
    },
    translate: function(offset) {
      this.min.add(offset);
      this.max.add(offset);
      return this;
    },
    equals: function(box) {
      return box.min.equals(this.min) && box.max.equals(this.max);
    }
  };
  THREE.Box3 = function(min, max) {
    this.min = (min !== undefined) ? min : new THREE.Vector3(+Infinity, +Infinity, +Infinity);
    this.max = (max !== undefined) ? max : new THREE.Vector3(-Infinity, -Infinity, -Infinity);
  };
  THREE.Box3.prototype = {
    constructor: THREE.Box3,
    set: function(min, max) {
      this.min.copy(min);
      this.max.copy(max);
      return this;
    },
    setFromArray: function(array) {
      var minX = +Infinity;
      var minY = +Infinity;
      var minZ = +Infinity;
      var maxX = -Infinity;
      var maxY = -Infinity;
      var maxZ = -Infinity;
      for (var i = 0,
          l = array.length; i < l; i += 3) {
        var x = array[i];
        var y = array[i + 1];
        var z = array[i + 2];
        if (x < minX)
          minX = x;
        if (y < minY)
          minY = y;
        if (z < minZ)
          minZ = z;
        if (x > maxX)
          maxX = x;
        if (y > maxY)
          maxY = y;
        if (z > maxZ)
          maxZ = z;
      }
      this.min.set(minX, minY, minZ);
      this.max.set(maxX, maxY, maxZ);
    },
    setFromPoints: function(points) {
      this.makeEmpty();
      for (var i = 0,
          il = points.length; i < il; i++) {
        this.expandByPoint(points[i]);
      }
      return this;
    },
    setFromCenterAndSize: function() {
      var v1 = new THREE.Vector3();
      return function setFromCenterAndSize(center, size) {
        var halfSize = v1.copy(size).multiplyScalar(0.5);
        this.min.copy(center).sub(halfSize);
        this.max.copy(center).add(halfSize);
        return this;
      };
    }(),
    setFromObject: function() {
      var v1 = new THREE.Vector3();
      return function setFromObject(object) {
        var scope = this;
        object.updateMatrixWorld(true);
        this.makeEmpty();
        object.traverse(function(node) {
          var geometry = node.geometry;
          if (geometry !== undefined) {
            if (geometry instanceof THREE.Geometry) {
              var vertices = geometry.vertices;
              for (var i = 0,
                  il = vertices.length; i < il; i++) {
                v1.copy(vertices[i]);
                v1.applyMatrix4(node.matrixWorld);
                scope.expandByPoint(v1);
              }
            } else if (geometry instanceof THREE.BufferGeometry && geometry.attributes['position'] !== undefined) {
              var positions = geometry.attributes['position'].array;
              for (var i = 0,
                  il = positions.length; i < il; i += 3) {
                v1.fromArray(positions, i);
                v1.applyMatrix4(node.matrixWorld);
                scope.expandByPoint(v1);
              }
            }
          }
        });
        return this;
      };
    }(),
    clone: function() {
      return new this.constructor().copy(this);
    },
    copy: function(box) {
      this.min.copy(box.min);
      this.max.copy(box.max);
      return this;
    },
    makeEmpty: function() {
      this.min.x = this.min.y = this.min.z = +Infinity;
      this.max.x = this.max.y = this.max.z = -Infinity;
      return this;
    },
    isEmpty: function() {
      return (this.max.x < this.min.x) || (this.max.y < this.min.y) || (this.max.z < this.min.z);
    },
    center: function(optionalTarget) {
      var result = optionalTarget || new THREE.Vector3();
      return result.addVectors(this.min, this.max).multiplyScalar(0.5);
    },
    size: function(optionalTarget) {
      var result = optionalTarget || new THREE.Vector3();
      return result.subVectors(this.max, this.min);
    },
    expandByPoint: function(point) {
      this.min.min(point);
      this.max.max(point);
      return this;
    },
    expandByVector: function(vector) {
      this.min.sub(vector);
      this.max.add(vector);
      return this;
    },
    expandByScalar: function(scalar) {
      this.min.addScalar(-scalar);
      this.max.addScalar(scalar);
      return this;
    },
    containsPoint: function(point) {
      if (point.x < this.min.x || point.x > this.max.x || point.y < this.min.y || point.y > this.max.y || point.z < this.min.z || point.z > this.max.z) {
        return false;
      }
      return true;
    },
    containsBox: function(box) {
      if ((this.min.x <= box.min.x) && (box.max.x <= this.max.x) && (this.min.y <= box.min.y) && (box.max.y <= this.max.y) && (this.min.z <= box.min.z) && (box.max.z <= this.max.z)) {
        return true;
      }
      return false;
    },
    getParameter: function(point, optionalTarget) {
      var result = optionalTarget || new THREE.Vector3();
      return result.set((point.x - this.min.x) / (this.max.x - this.min.x), (point.y - this.min.y) / (this.max.y - this.min.y), (point.z - this.min.z) / (this.max.z - this.min.z));
    },
    intersectsBox: function(box) {
      if (box.max.x < this.min.x || box.min.x > this.max.x || box.max.y < this.min.y || box.min.y > this.max.y || box.max.z < this.min.z || box.min.z > this.max.z) {
        return false;
      }
      return true;
    },
    intersectsSphere: (function() {
      var closestPoint;
      return function intersectsSphere(sphere) {
        if (closestPoint === undefined)
          closestPoint = new THREE.Vector3();
        this.clampPoint(sphere.center, closestPoint);
        return closestPoint.distanceToSquared(sphere.center) <= (sphere.radius * sphere.radius);
      };
    })(),
    intersectsPlane: function(plane) {
      var min,
          max;
      if (plane.normal.x > 0) {
        min = plane.normal.x * this.min.x;
        max = plane.normal.x * this.max.x;
      } else {
        min = plane.normal.x * this.max.x;
        max = plane.normal.x * this.min.x;
      }
      if (plane.normal.y > 0) {
        min += plane.normal.y * this.min.y;
        max += plane.normal.y * this.max.y;
      } else {
        min += plane.normal.y * this.max.y;
        max += plane.normal.y * this.min.y;
      }
      if (plane.normal.z > 0) {
        min += plane.normal.z * this.min.z;
        max += plane.normal.z * this.max.z;
      } else {
        min += plane.normal.z * this.max.z;
        max += plane.normal.z * this.min.z;
      }
      return (min <= plane.constant && max >= plane.constant);
    },
    clampPoint: function(point, optionalTarget) {
      var result = optionalTarget || new THREE.Vector3();
      return result.copy(point).clamp(this.min, this.max);
    },
    distanceToPoint: function() {
      var v1 = new THREE.Vector3();
      return function distanceToPoint(point) {
        var clampedPoint = v1.copy(point).clamp(this.min, this.max);
        return clampedPoint.sub(point).length();
      };
    }(),
    getBoundingSphere: function() {
      var v1 = new THREE.Vector3();
      return function getBoundingSphere(optionalTarget) {
        var result = optionalTarget || new THREE.Sphere();
        result.center = this.center();
        result.radius = this.size(v1).length() * 0.5;
        return result;
      };
    }(),
    intersect: function(box) {
      this.min.max(box.min);
      this.max.min(box.max);
      if (this.isEmpty())
        this.makeEmpty();
      return this;
    },
    union: function(box) {
      this.min.min(box.min);
      this.max.max(box.max);
      return this;
    },
    applyMatrix4: function() {
      var points = [new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3()];
      return function applyMatrix4(matrix) {
        if (this.isEmpty())
          return this;
        points[0].set(this.min.x, this.min.y, this.min.z).applyMatrix4(matrix);
        points[1].set(this.min.x, this.min.y, this.max.z).applyMatrix4(matrix);
        points[2].set(this.min.x, this.max.y, this.min.z).applyMatrix4(matrix);
        points[3].set(this.min.x, this.max.y, this.max.z).applyMatrix4(matrix);
        points[4].set(this.max.x, this.min.y, this.min.z).applyMatrix4(matrix);
        points[5].set(this.max.x, this.min.y, this.max.z).applyMatrix4(matrix);
        points[6].set(this.max.x, this.max.y, this.min.z).applyMatrix4(matrix);
        points[7].set(this.max.x, this.max.y, this.max.z).applyMatrix4(matrix);
        this.setFromPoints(points);
        return this;
      };
    }(),
    translate: function(offset) {
      this.min.add(offset);
      this.max.add(offset);
      return this;
    },
    equals: function(box) {
      return box.min.equals(this.min) && box.max.equals(this.max);
    }
  };
  THREE.Matrix3 = function() {
    this.elements = new Float32Array([1, 0, 0, 0, 1, 0, 0, 0, 1]);
    if (arguments.length > 0) {
      console.error('THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.');
    }
  };
  THREE.Matrix3.prototype = {
    constructor: THREE.Matrix3,
    set: function(n11, n12, n13, n21, n22, n23, n31, n32, n33) {
      var te = this.elements;
      te[0] = n11;
      te[1] = n21;
      te[2] = n31;
      te[3] = n12;
      te[4] = n22;
      te[5] = n32;
      te[6] = n13;
      te[7] = n23;
      te[8] = n33;
      return this;
    },
    identity: function() {
      this.set(1, 0, 0, 0, 1, 0, 0, 0, 1);
      return this;
    },
    clone: function() {
      return new this.constructor().fromArray(this.elements);
    },
    copy: function(m) {
      var me = m.elements;
      this.set(me[0], me[3], me[6], me[1], me[4], me[7], me[2], me[5], me[8]);
      return this;
    },
    setFromMatrix4: function(m) {
      var me = m.elements;
      this.set(me[0], me[4], me[8], me[1], me[5], me[9], me[2], me[6], me[10]);
      return this;
    },
    applyToVector3Array: function() {
      var v1;
      return function applyToVector3Array(array, offset, length) {
        if (v1 === undefined)
          v1 = new THREE.Vector3();
        if (offset === undefined)
          offset = 0;
        if (length === undefined)
          length = array.length;
        for (var i = 0,
            j = offset; i < length; i += 3, j += 3) {
          v1.fromArray(array, j);
          v1.applyMatrix3(this);
          v1.toArray(array, j);
        }
        return array;
      };
    }(),
    applyToBuffer: function() {
      var v1;
      return function applyToBuffer(buffer, offset, length) {
        if (v1 === undefined)
          v1 = new THREE.Vector3();
        if (offset === undefined)
          offset = 0;
        if (length === undefined)
          length = buffer.length / buffer.itemSize;
        for (var i = 0,
            j = offset; i < length; i++, j++) {
          v1.x = buffer.getX(j);
          v1.y = buffer.getY(j);
          v1.z = buffer.getZ(j);
          v1.applyMatrix3(this);
          buffer.setXYZ(v1.x, v1.y, v1.z);
        }
        return buffer;
      };
    }(),
    multiplyScalar: function(s) {
      var te = this.elements;
      te[0] *= s;
      te[3] *= s;
      te[6] *= s;
      te[1] *= s;
      te[4] *= s;
      te[7] *= s;
      te[2] *= s;
      te[5] *= s;
      te[8] *= s;
      return this;
    },
    determinant: function() {
      var te = this.elements;
      var a = te[0],
          b = te[1],
          c = te[2],
          d = te[3],
          e = te[4],
          f = te[5],
          g = te[6],
          h = te[7],
          i = te[8];
      return a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g;
    },
    getInverse: function(matrix, throwOnDegenerate) {
      if (matrix instanceof THREE.Matrix4) {
        console.error("THREE.Matrix3.getInverse no longer takes a Matrix4 argument.");
      }
      var me = matrix.elements,
          te = this.elements,
          n11 = me[0],
          n21 = me[1],
          n31 = me[2],
          n12 = me[3],
          n22 = me[4],
          n32 = me[5],
          n13 = me[6],
          n23 = me[7],
          n33 = me[8],
          t11 = n33 * n22 - n32 * n23,
          t12 = n32 * n13 - n33 * n12,
          t13 = n23 * n12 - n22 * n13,
          det = n11 * t11 + n21 * t12 + n31 * t13;
      if (det === 0) {
        var msg = "THREE.Matrix3.getInverse(): can't invert matrix, determinant is 0";
        if (throwOnDegenerate || false) {
          throw new Error(msg);
        } else {
          console.warn(msg);
        }
        return this.identity();
      }
      var detInv = 1 / det;
      te[0] = t11 * detInv;
      te[1] = (n31 * n23 - n33 * n21) * detInv;
      te[2] = (n32 * n21 - n31 * n22) * detInv;
      te[3] = t12 * detInv;
      te[4] = (n33 * n11 - n31 * n13) * detInv;
      te[5] = (n31 * n12 - n32 * n11) * detInv;
      te[6] = t13 * detInv;
      te[7] = (n21 * n13 - n23 * n11) * detInv;
      te[8] = (n22 * n11 - n21 * n12) * detInv;
      return this;
    },
    transpose: function() {
      var tmp,
          m = this.elements;
      tmp = m[1];
      m[1] = m[3];
      m[3] = tmp;
      tmp = m[2];
      m[2] = m[6];
      m[6] = tmp;
      tmp = m[5];
      m[5] = m[7];
      m[7] = tmp;
      return this;
    },
    flattenToArrayOffset: function(array, offset) {
      console.warn("THREE.Matrix3: .flattenToArrayOffset is deprecated " + "- just use .toArray instead.");
      return this.toArray(array, offset);
    },
    getNormalMatrix: function(matrix4) {
      return this.setFromMatrix4(matrix4).getInverse(this).transpose();
    },
    transposeIntoArray: function(r) {
      var m = this.elements;
      r[0] = m[0];
      r[1] = m[3];
      r[2] = m[6];
      r[3] = m[1];
      r[4] = m[4];
      r[5] = m[7];
      r[6] = m[2];
      r[7] = m[5];
      r[8] = m[8];
      return this;
    },
    fromArray: function(array) {
      this.elements.set(array);
      return this;
    },
    toArray: function(array, offset) {
      if (array === undefined)
        array = [];
      if (offset === undefined)
        offset = 0;
      var te = this.elements;
      array[offset] = te[0];
      array[offset + 1] = te[1];
      array[offset + 2] = te[2];
      array[offset + 3] = te[3];
      array[offset + 4] = te[4];
      array[offset + 5] = te[5];
      array[offset + 6] = te[6];
      array[offset + 7] = te[7];
      array[offset + 8] = te[8];
      return array;
    }
  };
  THREE.Matrix4 = function() {
    this.elements = new Float32Array([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1]);
    if (arguments.length > 0) {
      console.error('THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.');
    }
  };
  THREE.Matrix4.prototype = {
    constructor: THREE.Matrix4,
    set: function(n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44) {
      var te = this.elements;
      te[0] = n11;
      te[4] = n12;
      te[8] = n13;
      te[12] = n14;
      te[1] = n21;
      te[5] = n22;
      te[9] = n23;
      te[13] = n24;
      te[2] = n31;
      te[6] = n32;
      te[10] = n33;
      te[14] = n34;
      te[3] = n41;
      te[7] = n42;
      te[11] = n43;
      te[15] = n44;
      return this;
    },
    identity: function() {
      this.set(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
      return this;
    },
    clone: function() {
      return new THREE.Matrix4().fromArray(this.elements);
    },
    copy: function(m) {
      this.elements.set(m.elements);
      return this;
    },
    copyPosition: function(m) {
      var te = this.elements;
      var me = m.elements;
      te[12] = me[12];
      te[13] = me[13];
      te[14] = me[14];
      return this;
    },
    extractBasis: function(xAxis, yAxis, zAxis) {
      xAxis.setFromMatrixColumn(this, 0);
      yAxis.setFromMatrixColumn(this, 1);
      zAxis.setFromMatrixColumn(this, 2);
      return this;
    },
    makeBasis: function(xAxis, yAxis, zAxis) {
      this.set(xAxis.x, yAxis.x, zAxis.x, 0, xAxis.y, yAxis.y, zAxis.y, 0, xAxis.z, yAxis.z, zAxis.z, 0, 0, 0, 0, 1);
      return this;
    },
    extractRotation: function() {
      var v1;
      return function extractRotation(m) {
        if (v1 === undefined)
          v1 = new THREE.Vector3();
        var te = this.elements;
        var me = m.elements;
        var scaleX = 1 / v1.setFromMatrixColumn(m, 0).length();
        var scaleY = 1 / v1.setFromMatrixColumn(m, 1).length();
        var scaleZ = 1 / v1.setFromMatrixColumn(m, 2).length();
        te[0] = me[0] * scaleX;
        te[1] = me[1] * scaleX;
        te[2] = me[2] * scaleX;
        te[4] = me[4] * scaleY;
        te[5] = me[5] * scaleY;
        te[6] = me[6] * scaleY;
        te[8] = me[8] * scaleZ;
        te[9] = me[9] * scaleZ;
        te[10] = me[10] * scaleZ;
        return this;
      };
    }(),
    makeRotationFromEuler: function(euler) {
      if (euler instanceof THREE.Euler === false) {
        console.error('THREE.Matrix: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.');
      }
      var te = this.elements;
      var x = euler.x,
          y = euler.y,
          z = euler.z;
      var a = Math.cos(x),
          b = Math.sin(x);
      var c = Math.cos(y),
          d = Math.sin(y);
      var e = Math.cos(z),
          f = Math.sin(z);
      if (euler.order === 'XYZ') {
        var ae = a * e,
            af = a * f,
            be = b * e,
            bf = b * f;
        te[0] = c * e;
        te[4] = -c * f;
        te[8] = d;
        te[1] = af + be * d;
        te[5] = ae - bf * d;
        te[9] = -b * c;
        te[2] = bf - ae * d;
        te[6] = be + af * d;
        te[10] = a * c;
      } else if (euler.order === 'YXZ') {
        var ce = c * e,
            cf = c * f,
            de = d * e,
            df = d * f;
        te[0] = ce + df * b;
        te[4] = de * b - cf;
        te[8] = a * d;
        te[1] = a * f;
        te[5] = a * e;
        te[9] = -b;
        te[2] = cf * b - de;
        te[6] = df + ce * b;
        te[10] = a * c;
      } else if (euler.order === 'ZXY') {
        var ce = c * e,
            cf = c * f,
            de = d * e,
            df = d * f;
        te[0] = ce - df * b;
        te[4] = -a * f;
        te[8] = de + cf * b;
        te[1] = cf + de * b;
        te[5] = a * e;
        te[9] = df - ce * b;
        te[2] = -a * d;
        te[6] = b;
        te[10] = a * c;
      } else if (euler.order === 'ZYX') {
        var ae = a * e,
            af = a * f,
            be = b * e,
            bf = b * f;
        te[0] = c * e;
        te[4] = be * d - af;
        te[8] = ae * d + bf;
        te[1] = c * f;
        te[5] = bf * d + ae;
        te[9] = af * d - be;
        te[2] = -d;
        te[6] = b * c;
        te[10] = a * c;
      } else if (euler.order === 'YZX') {
        var ac = a * c,
            ad = a * d,
            bc = b * c,
            bd = b * d;
        te[0] = c * e;
        te[4] = bd - ac * f;
        te[8] = bc * f + ad;
        te[1] = f;
        te[5] = a * e;
        te[9] = -b * e;
        te[2] = -d * e;
        te[6] = ad * f + bc;
        te[10] = ac - bd * f;
      } else if (euler.order === 'XZY') {
        var ac = a * c,
            ad = a * d,
            bc = b * c,
            bd = b * d;
        te[0] = c * e;
        te[4] = -f;
        te[8] = d * e;
        te[1] = ac * f + bd;
        te[5] = a * e;
        te[9] = ad * f - bc;
        te[2] = bc * f - ad;
        te[6] = b * e;
        te[10] = bd * f + ac;
      }
      te[3] = 0;
      te[7] = 0;
      te[11] = 0;
      te[12] = 0;
      te[13] = 0;
      te[14] = 0;
      te[15] = 1;
      return this;
    },
    makeRotationFromQuaternion: function(q) {
      var te = this.elements;
      var x = q.x,
          y = q.y,
          z = q.z,
          w = q.w;
      var x2 = x + x,
          y2 = y + y,
          z2 = z + z;
      var xx = x * x2,
          xy = x * y2,
          xz = x * z2;
      var yy = y * y2,
          yz = y * z2,
          zz = z * z2;
      var wx = w * x2,
          wy = w * y2,
          wz = w * z2;
      te[0] = 1 - (yy + zz);
      te[4] = xy - wz;
      te[8] = xz + wy;
      te[1] = xy + wz;
      te[5] = 1 - (xx + zz);
      te[9] = yz - wx;
      te[2] = xz - wy;
      te[6] = yz + wx;
      te[10] = 1 - (xx + yy);
      te[3] = 0;
      te[7] = 0;
      te[11] = 0;
      te[12] = 0;
      te[13] = 0;
      te[14] = 0;
      te[15] = 1;
      return this;
    },
    lookAt: function() {
      var x,
          y,
          z;
      return function lookAt(eye, target, up) {
        if (x === undefined) {
          x = new THREE.Vector3();
          y = new THREE.Vector3();
          z = new THREE.Vector3();
        }
        var te = this.elements;
        z.subVectors(eye, target).normalize();
        if (z.lengthSq() === 0) {
          z.z = 1;
        }
        x.crossVectors(up, z).normalize();
        if (x.lengthSq() === 0) {
          z.z += 0.0001;
          x.crossVectors(up, z).normalize();
        }
        y.crossVectors(z, x);
        te[0] = x.x;
        te[4] = y.x;
        te[8] = z.x;
        te[1] = x.y;
        te[5] = y.y;
        te[9] = z.y;
        te[2] = x.z;
        te[6] = y.z;
        te[10] = z.z;
        return this;
      };
    }(),
    multiply: function(m, n) {
      if (n !== undefined) {
        console.warn('THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead.');
        return this.multiplyMatrices(m, n);
      }
      return this.multiplyMatrices(this, m);
    },
    premultiply: function(m) {
      return this.multiplyMatrices(m, this);
    },
    multiplyMatrices: function(a, b) {
      var ae = a.elements;
      var be = b.elements;
      var te = this.elements;
      var a11 = ae[0],
          a12 = ae[4],
          a13 = ae[8],
          a14 = ae[12];
      var a21 = ae[1],
          a22 = ae[5],
          a23 = ae[9],
          a24 = ae[13];
      var a31 = ae[2],
          a32 = ae[6],
          a33 = ae[10],
          a34 = ae[14];
      var a41 = ae[3],
          a42 = ae[7],
          a43 = ae[11],
          a44 = ae[15];
      var b11 = be[0],
          b12 = be[4],
          b13 = be[8],
          b14 = be[12];
      var b21 = be[1],
          b22 = be[5],
          b23 = be[9],
          b24 = be[13];
      var b31 = be[2],
          b32 = be[6],
          b33 = be[10],
          b34 = be[14];
      var b41 = be[3],
          b42 = be[7],
          b43 = be[11],
          b44 = be[15];
      te[0] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
      te[4] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
      te[8] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
      te[12] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;
      te[1] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
      te[5] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
      te[9] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
      te[13] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;
      te[2] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
      te[6] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
      te[10] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
      te[14] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;
      te[3] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
      te[7] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
      te[11] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
      te[15] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;
      return this;
    },
    multiplyToArray: function(a, b, r) {
      var te = this.elements;
      this.multiplyMatrices(a, b);
      r[0] = te[0];
      r[1] = te[1];
      r[2] = te[2];
      r[3] = te[3];
      r[4] = te[4];
      r[5] = te[5];
      r[6] = te[6];
      r[7] = te[7];
      r[8] = te[8];
      r[9] = te[9];
      r[10] = te[10];
      r[11] = te[11];
      r[12] = te[12];
      r[13] = te[13];
      r[14] = te[14];
      r[15] = te[15];
      return this;
    },
    multiplyScalar: function(s) {
      var te = this.elements;
      te[0] *= s;
      te[4] *= s;
      te[8] *= s;
      te[12] *= s;
      te[1] *= s;
      te[5] *= s;
      te[9] *= s;
      te[13] *= s;
      te[2] *= s;
      te[6] *= s;
      te[10] *= s;
      te[14] *= s;
      te[3] *= s;
      te[7] *= s;
      te[11] *= s;
      te[15] *= s;
      return this;
    },
    applyToVector3Array: function() {
      var v1;
      return function applyToVector3Array(array, offset, length) {
        if (v1 === undefined)
          v1 = new THREE.Vector3();
        if (offset === undefined)
          offset = 0;
        if (length === undefined)
          length = array.length;
        for (var i = 0,
            j = offset; i < length; i += 3, j += 3) {
          v1.fromArray(array, j);
          v1.applyMatrix4(this);
          v1.toArray(array, j);
        }
        return array;
      };
    }(),
    applyToBuffer: function() {
      var v1;
      return function applyToBuffer(buffer, offset, length) {
        if (v1 === undefined)
          v1 = new THREE.Vector3();
        if (offset === undefined)
          offset = 0;
        if (length === undefined)
          length = buffer.length / buffer.itemSize;
        for (var i = 0,
            j = offset; i < length; i++, j++) {
          v1.x = buffer.getX(j);
          v1.y = buffer.getY(j);
          v1.z = buffer.getZ(j);
          v1.applyMatrix4(this);
          buffer.setXYZ(v1.x, v1.y, v1.z);
        }
        return buffer;
      };
    }(),
    determinant: function() {
      var te = this.elements;
      var n11 = te[0],
          n12 = te[4],
          n13 = te[8],
          n14 = te[12];
      var n21 = te[1],
          n22 = te[5],
          n23 = te[9],
          n24 = te[13];
      var n31 = te[2],
          n32 = te[6],
          n33 = te[10],
          n34 = te[14];
      var n41 = te[3],
          n42 = te[7],
          n43 = te[11],
          n44 = te[15];
      return (n41 * (+n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34) + n42 * (+n11 * n23 * n34 - n11 * n24 * n33 + n14 * n21 * n33 - n13 * n21 * n34 + n13 * n24 * n31 - n14 * n23 * n31) + n43 * (+n11 * n24 * n32 - n11 * n22 * n34 - n14 * n21 * n32 + n12 * n21 * n34 + n14 * n22 * n31 - n12 * n24 * n31) + n44 * (-n13 * n22 * n31 - n11 * n23 * n32 + n11 * n22 * n33 + n13 * n21 * n32 - n12 * n21 * n33 + n12 * n23 * n31));
    },
    transpose: function() {
      var te = this.elements;
      var tmp;
      tmp = te[1];
      te[1] = te[4];
      te[4] = tmp;
      tmp = te[2];
      te[2] = te[8];
      te[8] = tmp;
      tmp = te[6];
      te[6] = te[9];
      te[9] = tmp;
      tmp = te[3];
      te[3] = te[12];
      te[12] = tmp;
      tmp = te[7];
      te[7] = te[13];
      te[13] = tmp;
      tmp = te[11];
      te[11] = te[14];
      te[14] = tmp;
      return this;
    },
    flattenToArrayOffset: function(array, offset) {
      console.warn("THREE.Matrix3: .flattenToArrayOffset is deprecated " + "- just use .toArray instead.");
      return this.toArray(array, offset);
    },
    getPosition: function() {
      var v1;
      return function getPosition() {
        if (v1 === undefined)
          v1 = new THREE.Vector3();
        console.warn('THREE.Matrix4: .getPosition() has been removed. Use Vector3.setFromMatrixPosition( matrix ) instead.');
        return v1.setFromMatrixColumn(this, 3);
      };
    }(),
    setPosition: function(v) {
      var te = this.elements;
      te[12] = v.x;
      te[13] = v.y;
      te[14] = v.z;
      return this;
    },
    getInverse: function(m, throwOnDegenerate) {
      var te = this.elements,
          me = m.elements,
          n11 = me[0],
          n21 = me[1],
          n31 = me[2],
          n41 = me[3],
          n12 = me[4],
          n22 = me[5],
          n32 = me[6],
          n42 = me[7],
          n13 = me[8],
          n23 = me[9],
          n33 = me[10],
          n43 = me[11],
          n14 = me[12],
          n24 = me[13],
          n34 = me[14],
          n44 = me[15],
          t11 = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44,
          t12 = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44,
          t13 = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44,
          t14 = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34;
      var det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14;
      if (det === 0) {
        var msg = "THREE.Matrix4.getInverse(): can't invert matrix, determinant is 0";
        if (throwOnDegenerate || false) {
          throw new Error(msg);
        } else {
          console.warn(msg);
        }
        return this.identity();
      }
      var detInv = 1 / det;
      te[0] = t11 * detInv;
      te[1] = (n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44) * detInv;
      te[2] = (n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44) * detInv;
      te[3] = (n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43) * detInv;
      te[4] = t12 * detInv;
      te[5] = (n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44) * detInv;
      te[6] = (n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44) * detInv;
      te[7] = (n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43) * detInv;
      te[8] = t13 * detInv;
      te[9] = (n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44) * detInv;
      te[10] = (n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44) * detInv;
      te[11] = (n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43) * detInv;
      te[12] = t14 * detInv;
      te[13] = (n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34) * detInv;
      te[14] = (n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34) * detInv;
      te[15] = (n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33) * detInv;
      return this;
    },
    scale: function(v) {
      var te = this.elements;
      var x = v.x,
          y = v.y,
          z = v.z;
      te[0] *= x;
      te[4] *= y;
      te[8] *= z;
      te[1] *= x;
      te[5] *= y;
      te[9] *= z;
      te[2] *= x;
      te[6] *= y;
      te[10] *= z;
      te[3] *= x;
      te[7] *= y;
      te[11] *= z;
      return this;
    },
    getMaxScaleOnAxis: function() {
      var te = this.elements;
      var scaleXSq = te[0] * te[0] + te[1] * te[1] + te[2] * te[2];
      var scaleYSq = te[4] * te[4] + te[5] * te[5] + te[6] * te[6];
      var scaleZSq = te[8] * te[8] + te[9] * te[9] + te[10] * te[10];
      return Math.sqrt(Math.max(scaleXSq, scaleYSq, scaleZSq));
    },
    makeTranslation: function(x, y, z) {
      this.set(1, 0, 0, x, 0, 1, 0, y, 0, 0, 1, z, 0, 0, 0, 1);
      return this;
    },
    makeRotationX: function(theta) {
      var c = Math.cos(theta),
          s = Math.sin(theta);
      this.set(1, 0, 0, 0, 0, c, -s, 0, 0, s, c, 0, 0, 0, 0, 1);
      return this;
    },
    makeRotationY: function(theta) {
      var c = Math.cos(theta),
          s = Math.sin(theta);
      this.set(c, 0, s, 0, 0, 1, 0, 0, -s, 0, c, 0, 0, 0, 0, 1);
      return this;
    },
    makeRotationZ: function(theta) {
      var c = Math.cos(theta),
          s = Math.sin(theta);
      this.set(c, -s, 0, 0, s, c, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
      return this;
    },
    makeRotationAxis: function(axis, angle) {
      var c = Math.cos(angle);
      var s = Math.sin(angle);
      var t = 1 - c;
      var x = axis.x,
          y = axis.y,
          z = axis.z;
      var tx = t * x,
          ty = t * y;
      this.set(tx * x + c, tx * y - s * z, tx * z + s * y, 0, tx * y + s * z, ty * y + c, ty * z - s * x, 0, tx * z - s * y, ty * z + s * x, t * z * z + c, 0, 0, 0, 0, 1);
      return this;
    },
    makeScale: function(x, y, z) {
      this.set(x, 0, 0, 0, 0, y, 0, 0, 0, 0, z, 0, 0, 0, 0, 1);
      return this;
    },
    compose: function(position, quaternion, scale) {
      this.makeRotationFromQuaternion(quaternion);
      this.scale(scale);
      this.setPosition(position);
      return this;
    },
    decompose: function() {
      var vector,
          matrix;
      return function decompose(position, quaternion, scale) {
        if (vector === undefined) {
          vector = new THREE.Vector3();
          matrix = new THREE.Matrix4();
        }
        var te = this.elements;
        var sx = vector.set(te[0], te[1], te[2]).length();
        var sy = vector.set(te[4], te[5], te[6]).length();
        var sz = vector.set(te[8], te[9], te[10]).length();
        var det = this.determinant();
        if (det < 0) {
          sx = -sx;
        }
        position.x = te[12];
        position.y = te[13];
        position.z = te[14];
        matrix.elements.set(this.elements);
        var invSX = 1 / sx;
        var invSY = 1 / sy;
        var invSZ = 1 / sz;
        matrix.elements[0] *= invSX;
        matrix.elements[1] *= invSX;
        matrix.elements[2] *= invSX;
        matrix.elements[4] *= invSY;
        matrix.elements[5] *= invSY;
        matrix.elements[6] *= invSY;
        matrix.elements[8] *= invSZ;
        matrix.elements[9] *= invSZ;
        matrix.elements[10] *= invSZ;
        quaternion.setFromRotationMatrix(matrix);
        scale.x = sx;
        scale.y = sy;
        scale.z = sz;
        return this;
      };
    }(),
    makeFrustum: function(left, right, bottom, top, near, far) {
      var te = this.elements;
      var x = 2 * near / (right - left);
      var y = 2 * near / (top - bottom);
      var a = (right + left) / (right - left);
      var b = (top + bottom) / (top - bottom);
      var c = -(far + near) / (far - near);
      var d = -2 * far * near / (far - near);
      te[0] = x;
      te[4] = 0;
      te[8] = a;
      te[12] = 0;
      te[1] = 0;
      te[5] = y;
      te[9] = b;
      te[13] = 0;
      te[2] = 0;
      te[6] = 0;
      te[10] = c;
      te[14] = d;
      te[3] = 0;
      te[7] = 0;
      te[11] = -1;
      te[15] = 0;
      return this;
    },
    makePerspective: function(fov, aspect, near, far) {
      var ymax = near * Math.tan(THREE.Math.DEG2RAD * fov * 0.5);
      var ymin = -ymax;
      var xmin = ymin * aspect;
      var xmax = ymax * aspect;
      return this.makeFrustum(xmin, xmax, ymin, ymax, near, far);
    },
    makeOrthographic: function(left, right, top, bottom, near, far) {
      var te = this.elements;
      var w = 1.0 / (right - left);
      var h = 1.0 / (top - bottom);
      var p = 1.0 / (far - near);
      var x = (right + left) * w;
      var y = (top + bottom) * h;
      var z = (far + near) * p;
      te[0] = 2 * w;
      te[4] = 0;
      te[8] = 0;
      te[12] = -x;
      te[1] = 0;
      te[5] = 2 * h;
      te[9] = 0;
      te[13] = -y;
      te[2] = 0;
      te[6] = 0;
      te[10] = -2 * p;
      te[14] = -z;
      te[3] = 0;
      te[7] = 0;
      te[11] = 0;
      te[15] = 1;
      return this;
    },
    equals: function(matrix) {
      var te = this.elements;
      var me = matrix.elements;
      for (var i = 0; i < 16; i++) {
        if (te[i] !== me[i])
          return false;
      }
      return true;
    },
    fromArray: function(array) {
      this.elements.set(array);
      return this;
    },
    toArray: function(array, offset) {
      if (array === undefined)
        array = [];
      if (offset === undefined)
        offset = 0;
      var te = this.elements;
      array[offset] = te[0];
      array[offset + 1] = te[1];
      array[offset + 2] = te[2];
      array[offset + 3] = te[3];
      array[offset + 4] = te[4];
      array[offset + 5] = te[5];
      array[offset + 6] = te[6];
      array[offset + 7] = te[7];
      array[offset + 8] = te[8];
      array[offset + 9] = te[9];
      array[offset + 10] = te[10];
      array[offset + 11] = te[11];
      array[offset + 12] = te[12];
      array[offset + 13] = te[13];
      array[offset + 14] = te[14];
      array[offset + 15] = te[15];
      return array;
    }
  };
  THREE.Ray = function(origin, direction) {
    this.origin = (origin !== undefined) ? origin : new THREE.Vector3();
    this.direction = (direction !== undefined) ? direction : new THREE.Vector3();
  };
  THREE.Ray.prototype = {
    constructor: THREE.Ray,
    set: function(origin, direction) {
      this.origin.copy(origin);
      this.direction.copy(direction);
      return this;
    },
    clone: function() {
      return new this.constructor().copy(this);
    },
    copy: function(ray) {
      this.origin.copy(ray.origin);
      this.direction.copy(ray.direction);
      return this;
    },
    at: function(t, optionalTarget) {
      var result = optionalTarget || new THREE.Vector3();
      return result.copy(this.direction).multiplyScalar(t).add(this.origin);
    },
    lookAt: function(v) {
      this.direction.copy(v).sub(this.origin).normalize();
      return this;
    },
    recast: function() {
      var v1 = new THREE.Vector3();
      return function recast(t) {
        this.origin.copy(this.at(t, v1));
        return this;
      };
    }(),
    closestPointToPoint: function(point, optionalTarget) {
      var result = optionalTarget || new THREE.Vector3();
      result.subVectors(point, this.origin);
      var directionDistance = result.dot(this.direction);
      if (directionDistance < 0) {
        return result.copy(this.origin);
      }
      return result.copy(this.direction).multiplyScalar(directionDistance).add(this.origin);
    },
    distanceToPoint: function(point) {
      return Math.sqrt(this.distanceSqToPoint(point));
    },
    distanceSqToPoint: function() {
      var v1 = new THREE.Vector3();
      return function distanceSqToPoint(point) {
        var directionDistance = v1.subVectors(point, this.origin).dot(this.direction);
        if (directionDistance < 0) {
          return this.origin.distanceToSquared(point);
        }
        v1.copy(this.direction).multiplyScalar(directionDistance).add(this.origin);
        return v1.distanceToSquared(point);
      };
    }(),
    distanceSqToSegment: function() {
      var segCenter = new THREE.Vector3();
      var segDir = new THREE.Vector3();
      var diff = new THREE.Vector3();
      return function distanceSqToSegment(v0, v1, optionalPointOnRay, optionalPointOnSegment) {
        segCenter.copy(v0).add(v1).multiplyScalar(0.5);
        segDir.copy(v1).sub(v0).normalize();
        diff.copy(this.origin).sub(segCenter);
        var segExtent = v0.distanceTo(v1) * 0.5;
        var a01 = -this.direction.dot(segDir);
        var b0 = diff.dot(this.direction);
        var b1 = -diff.dot(segDir);
        var c = diff.lengthSq();
        var det = Math.abs(1 - a01 * a01);
        var s0,
            s1,
            sqrDist,
            extDet;
        if (det > 0) {
          s0 = a01 * b1 - b0;
          s1 = a01 * b0 - b1;
          extDet = segExtent * det;
          if (s0 >= 0) {
            if (s1 >= -extDet) {
              if (s1 <= extDet) {
                var invDet = 1 / det;
                s0 *= invDet;
                s1 *= invDet;
                sqrDist = s0 * (s0 + a01 * s1 + 2 * b0) + s1 * (a01 * s0 + s1 + 2 * b1) + c;
              } else {
                s1 = segExtent;
                s0 = Math.max(0, -(a01 * s1 + b0));
                sqrDist = -s0 * s0 + s1 * (s1 + 2 * b1) + c;
              }
            } else {
              s1 = -segExtent;
              s0 = Math.max(0, -(a01 * s1 + b0));
              sqrDist = -s0 * s0 + s1 * (s1 + 2 * b1) + c;
            }
          } else {
            if (s1 <= -extDet) {
              s0 = Math.max(0, -(-a01 * segExtent + b0));
              s1 = (s0 > 0) ? -segExtent : Math.min(Math.max(-segExtent, -b1), segExtent);
              sqrDist = -s0 * s0 + s1 * (s1 + 2 * b1) + c;
            } else if (s1 <= extDet) {
              s0 = 0;
              s1 = Math.min(Math.max(-segExtent, -b1), segExtent);
              sqrDist = s1 * (s1 + 2 * b1) + c;
            } else {
              s0 = Math.max(0, -(a01 * segExtent + b0));
              s1 = (s0 > 0) ? segExtent : Math.min(Math.max(-segExtent, -b1), segExtent);
              sqrDist = -s0 * s0 + s1 * (s1 + 2 * b1) + c;
            }
          }
        } else {
          s1 = (a01 > 0) ? -segExtent : segExtent;
          s0 = Math.max(0, -(a01 * s1 + b0));
          sqrDist = -s0 * s0 + s1 * (s1 + 2 * b1) + c;
        }
        if (optionalPointOnRay) {
          optionalPointOnRay.copy(this.direction).multiplyScalar(s0).add(this.origin);
        }
        if (optionalPointOnSegment) {
          optionalPointOnSegment.copy(segDir).multiplyScalar(s1).add(segCenter);
        }
        return sqrDist;
      };
    }(),
    intersectSphere: function() {
      var v1 = new THREE.Vector3();
      return function intersectSphere(sphere, optionalTarget) {
        v1.subVectors(sphere.center, this.origin);
        var tca = v1.dot(this.direction);
        var d2 = v1.dot(v1) - tca * tca;
        var radius2 = sphere.radius * sphere.radius;
        if (d2 > radius2)
          return null;
        var thc = Math.sqrt(radius2 - d2);
        var t0 = tca - thc;
        var t1 = tca + thc;
        if (t0 < 0 && t1 < 0)
          return null;
        if (t0 < 0)
          return this.at(t1, optionalTarget);
        return this.at(t0, optionalTarget);
      };
    }(),
    intersectsSphere: function(sphere) {
      return this.distanceToPoint(sphere.center) <= sphere.radius;
    },
    distanceToPlane: function(plane) {
      var denominator = plane.normal.dot(this.direction);
      if (denominator === 0) {
        if (plane.distanceToPoint(this.origin) === 0) {
          return 0;
        }
        return null;
      }
      var t = -(this.origin.dot(plane.normal) + plane.constant) / denominator;
      return t >= 0 ? t : null;
    },
    intersectPlane: function(plane, optionalTarget) {
      var t = this.distanceToPlane(plane);
      if (t === null) {
        return null;
      }
      return this.at(t, optionalTarget);
    },
    intersectsPlane: function(plane) {
      var distToPoint = plane.distanceToPoint(this.origin);
      if (distToPoint === 0) {
        return true;
      }
      var denominator = plane.normal.dot(this.direction);
      if (denominator * distToPoint < 0) {
        return true;
      }
      return false;
    },
    intersectBox: function(box, optionalTarget) {
      var tmin,
          tmax,
          tymin,
          tymax,
          tzmin,
          tzmax;
      var invdirx = 1 / this.direction.x,
          invdiry = 1 / this.direction.y,
          invdirz = 1 / this.direction.z;
      var origin = this.origin;
      if (invdirx >= 0) {
        tmin = (box.min.x - origin.x) * invdirx;
        tmax = (box.max.x - origin.x) * invdirx;
      } else {
        tmin = (box.max.x - origin.x) * invdirx;
        tmax = (box.min.x - origin.x) * invdirx;
      }
      if (invdiry >= 0) {
        tymin = (box.min.y - origin.y) * invdiry;
        tymax = (box.max.y - origin.y) * invdiry;
      } else {
        tymin = (box.max.y - origin.y) * invdiry;
        tymax = (box.min.y - origin.y) * invdiry;
      }
      if ((tmin > tymax) || (tymin > tmax))
        return null;
      if (tymin > tmin || tmin !== tmin)
        tmin = tymin;
      if (tymax < tmax || tmax !== tmax)
        tmax = tymax;
      if (invdirz >= 0) {
        tzmin = (box.min.z - origin.z) * invdirz;
        tzmax = (box.max.z - origin.z) * invdirz;
      } else {
        tzmin = (box.max.z - origin.z) * invdirz;
        tzmax = (box.min.z - origin.z) * invdirz;
      }
      if ((tmin > tzmax) || (tzmin > tmax))
        return null;
      if (tzmin > tmin || tmin !== tmin)
        tmin = tzmin;
      if (tzmax < tmax || tmax !== tmax)
        tmax = tzmax;
      if (tmax < 0)
        return null;
      return this.at(tmin >= 0 ? tmin : tmax, optionalTarget);
    },
    intersectsBox: (function() {
      var v = new THREE.Vector3();
      return function intersectsBox(box) {
        return this.intersectBox(box, v) !== null;
      };
    })(),
    intersectTriangle: function() {
      var diff = new THREE.Vector3();
      var edge1 = new THREE.Vector3();
      var edge2 = new THREE.Vector3();
      var normal = new THREE.Vector3();
      return function intersectTriangle(a, b, c, backfaceCulling, optionalTarget) {
        edge1.subVectors(b, a);
        edge2.subVectors(c, a);
        normal.crossVectors(edge1, edge2);
        var DdN = this.direction.dot(normal);
        var sign;
        if (DdN > 0) {
          if (backfaceCulling)
            return null;
          sign = 1;
        } else if (DdN < 0) {
          sign = -1;
          DdN = -DdN;
        } else {
          return null;
        }
        diff.subVectors(this.origin, a);
        var DdQxE2 = sign * this.direction.dot(edge2.crossVectors(diff, edge2));
        if (DdQxE2 < 0) {
          return null;
        }
        var DdE1xQ = sign * this.direction.dot(edge1.cross(diff));
        if (DdE1xQ < 0) {
          return null;
        }
        if (DdQxE2 + DdE1xQ > DdN) {
          return null;
        }
        var QdN = -sign * diff.dot(normal);
        if (QdN < 0) {
          return null;
        }
        return this.at(QdN / DdN, optionalTarget);
      };
    }(),
    applyMatrix4: function(matrix4) {
      this.direction.add(this.origin).applyMatrix4(matrix4);
      this.origin.applyMatrix4(matrix4);
      this.direction.sub(this.origin);
      this.direction.normalize();
      return this;
    },
    equals: function(ray) {
      return ray.origin.equals(this.origin) && ray.direction.equals(this.direction);
    }
  };
  THREE.Sphere = function(center, radius) {
    this.center = (center !== undefined) ? center : new THREE.Vector3();
    this.radius = (radius !== undefined) ? radius : 0;
  };
  THREE.Sphere.prototype = {
    constructor: THREE.Sphere,
    set: function(center, radius) {
      this.center.copy(center);
      this.radius = radius;
      return this;
    },
    setFromPoints: function() {
      var box = new THREE.Box3();
      return function setFromPoints(points, optionalCenter) {
        var center = this.center;
        if (optionalCenter !== undefined) {
          center.copy(optionalCenter);
        } else {
          box.setFromPoints(points).center(center);
        }
        var maxRadiusSq = 0;
        for (var i = 0,
            il = points.length; i < il; i++) {
          maxRadiusSq = Math.max(maxRadiusSq, center.distanceToSquared(points[i]));
        }
        this.radius = Math.sqrt(maxRadiusSq);
        return this;
      };
    }(),
    clone: function() {
      return new this.constructor().copy(this);
    },
    copy: function(sphere) {
      this.center.copy(sphere.center);
      this.radius = sphere.radius;
      return this;
    },
    empty: function() {
      return (this.radius <= 0);
    },
    containsPoint: function(point) {
      return (point.distanceToSquared(this.center) <= (this.radius * this.radius));
    },
    distanceToPoint: function(point) {
      return (point.distanceTo(this.center) - this.radius);
    },
    intersectsSphere: function(sphere) {
      var radiusSum = this.radius + sphere.radius;
      return sphere.center.distanceToSquared(this.center) <= (radiusSum * radiusSum);
    },
    intersectsBox: function(box) {
      return box.intersectsSphere(this);
    },
    intersectsPlane: function(plane) {
      return Math.abs(this.center.dot(plane.normal) - plane.constant) <= this.radius;
    },
    clampPoint: function(point, optionalTarget) {
      var deltaLengthSq = this.center.distanceToSquared(point);
      var result = optionalTarget || new THREE.Vector3();
      result.copy(point);
      if (deltaLengthSq > (this.radius * this.radius)) {
        result.sub(this.center).normalize();
        result.multiplyScalar(this.radius).add(this.center);
      }
      return result;
    },
    getBoundingBox: function(optionalTarget) {
      var box = optionalTarget || new THREE.Box3();
      box.set(this.center, this.center);
      box.expandByScalar(this.radius);
      return box;
    },
    applyMatrix4: function(matrix) {
      this.center.applyMatrix4(matrix);
      this.radius = this.radius * matrix.getMaxScaleOnAxis();
      return this;
    },
    translate: function(offset) {
      this.center.add(offset);
      return this;
    },
    equals: function(sphere) {
      return sphere.center.equals(this.center) && (sphere.radius === this.radius);
    }
  };
  THREE.Frustum = function(p0, p1, p2, p3, p4, p5) {
    this.planes = [(p0 !== undefined) ? p0 : new THREE.Plane(), (p1 !== undefined) ? p1 : new THREE.Plane(), (p2 !== undefined) ? p2 : new THREE.Plane(), (p3 !== undefined) ? p3 : new THREE.Plane(), (p4 !== undefined) ? p4 : new THREE.Plane(), (p5 !== undefined) ? p5 : new THREE.Plane()];
  };
  THREE.Frustum.prototype = {
    constructor: THREE.Frustum,
    set: function(p0, p1, p2, p3, p4, p5) {
      var planes = this.planes;
      planes[0].copy(p0);
      planes[1].copy(p1);
      planes[2].copy(p2);
      planes[3].copy(p3);
      planes[4].copy(p4);
      planes[5].copy(p5);
      return this;
    },
    clone: function() {
      return new this.constructor().copy(this);
    },
    copy: function(frustum) {
      var planes = this.planes;
      for (var i = 0; i < 6; i++) {
        planes[i].copy(frustum.planes[i]);
      }
      return this;
    },
    setFromMatrix: function(m) {
      var planes = this.planes;
      var me = m.elements;
      var me0 = me[0],
          me1 = me[1],
          me2 = me[2],
          me3 = me[3];
      var me4 = me[4],
          me5 = me[5],
          me6 = me[6],
          me7 = me[7];
      var me8 = me[8],
          me9 = me[9],
          me10 = me[10],
          me11 = me[11];
      var me12 = me[12],
          me13 = me[13],
          me14 = me[14],
          me15 = me[15];
      planes[0].setComponents(me3 - me0, me7 - me4, me11 - me8, me15 - me12).normalize();
      planes[1].setComponents(me3 + me0, me7 + me4, me11 + me8, me15 + me12).normalize();
      planes[2].setComponents(me3 + me1, me7 + me5, me11 + me9, me15 + me13).normalize();
      planes[3].setComponents(me3 - me1, me7 - me5, me11 - me9, me15 - me13).normalize();
      planes[4].setComponents(me3 - me2, me7 - me6, me11 - me10, me15 - me14).normalize();
      planes[5].setComponents(me3 + me2, me7 + me6, me11 + me10, me15 + me14).normalize();
      return this;
    },
    intersectsObject: function() {
      var sphere = new THREE.Sphere();
      return function intersectsObject(object) {
        var geometry = object.geometry;
        if (geometry.boundingSphere === null)
          geometry.computeBoundingSphere();
        sphere.copy(geometry.boundingSphere).applyMatrix4(object.matrixWorld);
        return this.intersectsSphere(sphere);
      };
    }(),
    intersectsSprite: function() {
      var sphere = new THREE.Sphere();
      return function intersectsSprite(sprite) {
        sphere.center.set(0, 0, 0);
        sphere.radius = 0.7071067811865476;
        sphere.applyMatrix4(sprite.matrixWorld);
        return this.intersectsSphere(sphere);
      };
    }(),
    intersectsSphere: function(sphere) {
      var planes = this.planes;
      var center = sphere.center;
      var negRadius = -sphere.radius;
      for (var i = 0; i < 6; i++) {
        var distance = planes[i].distanceToPoint(center);
        if (distance < negRadius) {
          return false;
        }
      }
      return true;
    },
    intersectsBox: function() {
      var p1 = new THREE.Vector3(),
          p2 = new THREE.Vector3();
      return function intersectsBox(box) {
        var planes = this.planes;
        for (var i = 0; i < 6; i++) {
          var plane = planes[i];
          p1.x = plane.normal.x > 0 ? box.min.x : box.max.x;
          p2.x = plane.normal.x > 0 ? box.max.x : box.min.x;
          p1.y = plane.normal.y > 0 ? box.min.y : box.max.y;
          p2.y = plane.normal.y > 0 ? box.max.y : box.min.y;
          p1.z = plane.normal.z > 0 ? box.min.z : box.max.z;
          p2.z = plane.normal.z > 0 ? box.max.z : box.min.z;
          var d1 = plane.distanceToPoint(p1);
          var d2 = plane.distanceToPoint(p2);
          if (d1 < 0 && d2 < 0) {
            return false;
          }
        }
        return true;
      };
    }(),
    containsPoint: function(point) {
      var planes = this.planes;
      for (var i = 0; i < 6; i++) {
        if (planes[i].distanceToPoint(point) < 0) {
          return false;
        }
      }
      return true;
    }
  };
  THREE.Plane = function(normal, constant) {
    this.normal = (normal !== undefined) ? normal : new THREE.Vector3(1, 0, 0);
    this.constant = (constant !== undefined) ? constant : 0;
  };
  THREE.Plane.prototype = {
    constructor: THREE.Plane,
    set: function(normal, constant) {
      this.normal.copy(normal);
      this.constant = constant;
      return this;
    },
    setComponents: function(x, y, z, w) {
      this.normal.set(x, y, z);
      this.constant = w;
      return this;
    },
    setFromNormalAndCoplanarPoint: function(normal, point) {
      this.normal.copy(normal);
      this.constant = -point.dot(this.normal);
      return this;
    },
    setFromCoplanarPoints: function() {
      var v1 = new THREE.Vector3();
      var v2 = new THREE.Vector3();
      return function setFromCoplanarPoints(a, b, c) {
        var normal = v1.subVectors(c, b).cross(v2.subVectors(a, b)).normalize();
        this.setFromNormalAndCoplanarPoint(normal, a);
        return this;
      };
    }(),
    clone: function() {
      return new this.constructor().copy(this);
    },
    copy: function(plane) {
      this.normal.copy(plane.normal);
      this.constant = plane.constant;
      return this;
    },
    normalize: function() {
      var inverseNormalLength = 1.0 / this.normal.length();
      this.normal.multiplyScalar(inverseNormalLength);
      this.constant *= inverseNormalLength;
      return this;
    },
    negate: function() {
      this.constant *= -1;
      this.normal.negate();
      return this;
    },
    distanceToPoint: function(point) {
      return this.normal.dot(point) + this.constant;
    },
    distanceToSphere: function(sphere) {
      return this.distanceToPoint(sphere.center) - sphere.radius;
    },
    projectPoint: function(point, optionalTarget) {
      return this.orthoPoint(point, optionalTarget).sub(point).negate();
    },
    orthoPoint: function(point, optionalTarget) {
      var perpendicularMagnitude = this.distanceToPoint(point);
      var result = optionalTarget || new THREE.Vector3();
      return result.copy(this.normal).multiplyScalar(perpendicularMagnitude);
    },
    intersectLine: function() {
      var v1 = new THREE.Vector3();
      return function intersectLine(line, optionalTarget) {
        var result = optionalTarget || new THREE.Vector3();
        var direction = line.delta(v1);
        var denominator = this.normal.dot(direction);
        if (denominator === 0) {
          if (this.distanceToPoint(line.start) === 0) {
            return result.copy(line.start);
          }
          return undefined;
        }
        var t = -(line.start.dot(this.normal) + this.constant) / denominator;
        if (t < 0 || t > 1) {
          return undefined;
        }
        return result.copy(direction).multiplyScalar(t).add(line.start);
      };
    }(),
    intersectsLine: function(line) {
      var startSign = this.distanceToPoint(line.start);
      var endSign = this.distanceToPoint(line.end);
      return (startSign < 0 && endSign > 0) || (endSign < 0 && startSign > 0);
    },
    intersectsBox: function(box) {
      return box.intersectsPlane(this);
    },
    intersectsSphere: function(sphere) {
      return sphere.intersectsPlane(this);
    },
    coplanarPoint: function(optionalTarget) {
      var result = optionalTarget || new THREE.Vector3();
      return result.copy(this.normal).multiplyScalar(-this.constant);
    },
    applyMatrix4: function() {
      var v1 = new THREE.Vector3();
      var m1 = new THREE.Matrix3();
      return function applyMatrix4(matrix, optionalNormalMatrix) {
        var referencePoint = this.coplanarPoint(v1).applyMatrix4(matrix);
        var normalMatrix = optionalNormalMatrix || m1.getNormalMatrix(matrix);
        var normal = this.normal.applyMatrix3(normalMatrix).normalize();
        this.constant = -referencePoint.dot(normal);
        return this;
      };
    }(),
    translate: function(offset) {
      this.constant = this.constant - offset.dot(this.normal);
      return this;
    },
    equals: function(plane) {
      return plane.normal.equals(this.normal) && (plane.constant === this.constant);
    }
  };
  THREE.Spherical = function(radius, phi, theta) {
    this.radius = (radius !== undefined) ? radius : 1.0;
    this.phi = (phi !== undefined) ? phi : 0;
    this.theta = (theta !== undefined) ? theta : 0;
    return this;
  };
  THREE.Spherical.prototype = {
    constructor: THREE.Spherical,
    set: function(radius, phi, theta) {
      this.radius = radius;
      this.phi = phi;
      this.theta = theta;
      return this;
    },
    clone: function() {
      return new this.constructor().copy(this);
    },
    copy: function(other) {
      this.radius.copy(other.radius);
      this.phi.copy(other.phi);
      this.theta.copy(other.theta);
      return this;
    },
    makeSafe: function() {
      var EPS = 0.000001;
      this.phi = Math.max(EPS, Math.min(Math.PI - EPS, this.phi));
      return this;
    },
    setFromVector3: function(vec3) {
      this.radius = vec3.length();
      if (this.radius === 0) {
        this.theta = 0;
        this.phi = 0;
      } else {
        this.theta = Math.atan2(vec3.x, vec3.z);
        this.phi = Math.acos(THREE.Math.clamp(vec3.y / this.radius, -1, 1));
      }
      return this;
    }
  };
  THREE.Math = {
    DEG2RAD: Math.PI / 180,
    RAD2DEG: 180 / Math.PI,
    generateUUID: function() {
      var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
      var uuid = new Array(36);
      var rnd = 0,
          r;
      return function generateUUID() {
        for (var i = 0; i < 36; i++) {
          if (i === 8 || i === 13 || i === 18 || i === 23) {
            uuid[i] = '-';
          } else if (i === 14) {
            uuid[i] = '4';
          } else {
            if (rnd <= 0x02)
              rnd = 0x2000000 + (Math.random() * 0x1000000) | 0;
            r = rnd & 0xf;
            rnd = rnd >> 4;
            uuid[i] = chars[(i === 19) ? (r & 0x3) | 0x8 : r];
          }
        }
        return uuid.join('');
      };
    }(),
    clamp: function(value, min, max) {
      return Math.max(min, Math.min(max, value));
    },
    euclideanModulo: function(n, m) {
      return ((n % m) + m) % m;
    },
    mapLinear: function(x, a1, a2, b1, b2) {
      return b1 + (x - a1) * (b2 - b1) / (a2 - a1);
    },
    smoothstep: function(x, min, max) {
      if (x <= min)
        return 0;
      if (x >= max)
        return 1;
      x = (x - min) / (max - min);
      return x * x * (3 - 2 * x);
    },
    smootherstep: function(x, min, max) {
      if (x <= min)
        return 0;
      if (x >= max)
        return 1;
      x = (x - min) / (max - min);
      return x * x * x * (x * (x * 6 - 15) + 10);
    },
    random16: function() {
      console.warn('THREE.Math.random16() has been deprecated. Use Math.random() instead.');
      return Math.random();
    },
    randInt: function(low, high) {
      return low + Math.floor(Math.random() * (high - low + 1));
    },
    randFloat: function(low, high) {
      return low + Math.random() * (high - low);
    },
    randFloatSpread: function(range) {
      return range * (0.5 - Math.random());
    },
    degToRad: function(degrees) {
      return degrees * THREE.Math.DEG2RAD;
    },
    radToDeg: function(radians) {
      return radians * THREE.Math.RAD2DEG;
    },
    isPowerOfTwo: function(value) {
      return (value & (value - 1)) === 0 && value !== 0;
    },
    nearestPowerOfTwo: function(value) {
      return Math.pow(2, Math.round(Math.log(value) / Math.LN2));
    },
    nextPowerOfTwo: function(value) {
      value--;
      value |= value >> 1;
      value |= value >> 2;
      value |= value >> 4;
      value |= value >> 8;
      value |= value >> 16;
      value++;
      return value;
    }
  };
  THREE.Spline = function(points) {
    this.points = points;
    var c = [],
        v3 = {
          x: 0,
          y: 0,
          z: 0
        },
        point,
        intPoint,
        weight,
        w2,
        w3,
        pa,
        pb,
        pc,
        pd;
    this.initFromArray = function(a) {
      this.points = [];
      for (var i = 0; i < a.length; i++) {
        this.points[i] = {
          x: a[i][0],
          y: a[i][1],
          z: a[i][2]
        };
      }
    };
    this.getPoint = function(k) {
      point = (this.points.length - 1) * k;
      intPoint = Math.floor(point);
      weight = point - intPoint;
      c[0] = intPoint === 0 ? intPoint : intPoint - 1;
      c[1] = intPoint;
      c[2] = intPoint > this.points.length - 2 ? this.points.length - 1 : intPoint + 1;
      c[3] = intPoint > this.points.length - 3 ? this.points.length - 1 : intPoint + 2;
      pa = this.points[c[0]];
      pb = this.points[c[1]];
      pc = this.points[c[2]];
      pd = this.points[c[3]];
      w2 = weight * weight;
      w3 = weight * w2;
      v3.x = interpolate(pa.x, pb.x, pc.x, pd.x, weight, w2, w3);
      v3.y = interpolate(pa.y, pb.y, pc.y, pd.y, weight, w2, w3);
      v3.z = interpolate(pa.z, pb.z, pc.z, pd.z, weight, w2, w3);
      return v3;
    };
    this.getControlPointsArray = function() {
      var i,
          p,
          l = this.points.length,
          coords = [];
      for (i = 0; i < l; i++) {
        p = this.points[i];
        coords[i] = [p.x, p.y, p.z];
      }
      return coords;
    };
    this.getLength = function(nSubDivisions) {
      var i,
          index,
          nSamples,
          position,
          point = 0,
          intPoint = 0,
          oldIntPoint = 0,
          oldPosition = new THREE.Vector3(),
          tmpVec = new THREE.Vector3(),
          chunkLengths = [],
          totalLength = 0;
      chunkLengths[0] = 0;
      if (!nSubDivisions)
        nSubDivisions = 100;
      nSamples = this.points.length * nSubDivisions;
      oldPosition.copy(this.points[0]);
      for (i = 1; i < nSamples; i++) {
        index = i / nSamples;
        position = this.getPoint(index);
        tmpVec.copy(position);
        totalLength += tmpVec.distanceTo(oldPosition);
        oldPosition.copy(position);
        point = (this.points.length - 1) * index;
        intPoint = Math.floor(point);
        if (intPoint !== oldIntPoint) {
          chunkLengths[intPoint] = totalLength;
          oldIntPoint = intPoint;
        }
      }
      chunkLengths[chunkLengths.length] = totalLength;
      return {
        chunks: chunkLengths,
        total: totalLength
      };
    };
    this.reparametrizeByArcLength = function(samplingCoef) {
      var i,
          j,
          index,
          indexCurrent,
          indexNext,
          realDistance,
          sampling,
          position,
          newpoints = [],
          tmpVec = new THREE.Vector3(),
          sl = this.getLength();
      newpoints.push(tmpVec.copy(this.points[0]).clone());
      for (i = 1; i < this.points.length; i++) {
        realDistance = sl.chunks[i] - sl.chunks[i - 1];
        sampling = Math.ceil(samplingCoef * realDistance / sl.total);
        indexCurrent = (i - 1) / (this.points.length - 1);
        indexNext = i / (this.points.length - 1);
        for (j = 1; j < sampling - 1; j++) {
          index = indexCurrent + j * (1 / sampling) * (indexNext - indexCurrent);
          position = this.getPoint(index);
          newpoints.push(tmpVec.copy(position).clone());
        }
        newpoints.push(tmpVec.copy(this.points[i]).clone());
      }
      this.points = newpoints;
    };
    function interpolate(p0, p1, p2, p3, t, t2, t3) {
      var v0 = (p2 - p0) * 0.5,
          v1 = (p3 - p1) * 0.5;
      return (2 * (p1 - p2) + v0 + v1) * t3 + (-3 * (p1 - p2) - 2 * v0 - v1) * t2 + v0 * t + p1;
    }
  };
  THREE.Triangle = function(a, b, c) {
    this.a = (a !== undefined) ? a : new THREE.Vector3();
    this.b = (b !== undefined) ? b : new THREE.Vector3();
    this.c = (c !== undefined) ? c : new THREE.Vector3();
  };
  THREE.Triangle.normal = function() {
    var v0 = new THREE.Vector3();
    return function normal(a, b, c, optionalTarget) {
      var result = optionalTarget || new THREE.Vector3();
      result.subVectors(c, b);
      v0.subVectors(a, b);
      result.cross(v0);
      var resultLengthSq = result.lengthSq();
      if (resultLengthSq > 0) {
        return result.multiplyScalar(1 / Math.sqrt(resultLengthSq));
      }
      return result.set(0, 0, 0);
    };
  }();
  THREE.Triangle.barycoordFromPoint = function() {
    var v0 = new THREE.Vector3();
    var v1 = new THREE.Vector3();
    var v2 = new THREE.Vector3();
    return function barycoordFromPoint(point, a, b, c, optionalTarget) {
      v0.subVectors(c, a);
      v1.subVectors(b, a);
      v2.subVectors(point, a);
      var dot00 = v0.dot(v0);
      var dot01 = v0.dot(v1);
      var dot02 = v0.dot(v2);
      var dot11 = v1.dot(v1);
      var dot12 = v1.dot(v2);
      var denom = (dot00 * dot11 - dot01 * dot01);
      var result = optionalTarget || new THREE.Vector3();
      if (denom === 0) {
        return result.set(-2, -1, -1);
      }
      var invDenom = 1 / denom;
      var u = (dot11 * dot02 - dot01 * dot12) * invDenom;
      var v = (dot00 * dot12 - dot01 * dot02) * invDenom;
      return result.set(1 - u - v, v, u);
    };
  }();
  THREE.Triangle.containsPoint = function() {
    var v1 = new THREE.Vector3();
    return function containsPoint(point, a, b, c) {
      var result = THREE.Triangle.barycoordFromPoint(point, a, b, c, v1);
      return (result.x >= 0) && (result.y >= 0) && ((result.x + result.y) <= 1);
    };
  }();
  THREE.Triangle.prototype = {
    constructor: THREE.Triangle,
    set: function(a, b, c) {
      this.a.copy(a);
      this.b.copy(b);
      this.c.copy(c);
      return this;
    },
    setFromPointsAndIndices: function(points, i0, i1, i2) {
      this.a.copy(points[i0]);
      this.b.copy(points[i1]);
      this.c.copy(points[i2]);
      return this;
    },
    clone: function() {
      return new this.constructor().copy(this);
    },
    copy: function(triangle) {
      this.a.copy(triangle.a);
      this.b.copy(triangle.b);
      this.c.copy(triangle.c);
      return this;
    },
    area: function() {
      var v0 = new THREE.Vector3();
      var v1 = new THREE.Vector3();
      return function area() {
        v0.subVectors(this.c, this.b);
        v1.subVectors(this.a, this.b);
        return v0.cross(v1).length() * 0.5;
      };
    }(),
    midpoint: function(optionalTarget) {
      var result = optionalTarget || new THREE.Vector3();
      return result.addVectors(this.a, this.b).add(this.c).multiplyScalar(1 / 3);
    },
    normal: function(optionalTarget) {
      return THREE.Triangle.normal(this.a, this.b, this.c, optionalTarget);
    },
    plane: function(optionalTarget) {
      var result = optionalTarget || new THREE.Plane();
      return result.setFromCoplanarPoints(this.a, this.b, this.c);
    },
    barycoordFromPoint: function(point, optionalTarget) {
      return THREE.Triangle.barycoordFromPoint(point, this.a, this.b, this.c, optionalTarget);
    },
    containsPoint: function(point) {
      return THREE.Triangle.containsPoint(point, this.a, this.b, this.c);
    },
    closestPointToPoint: function() {
      var plane,
          edgeList,
          projectedPoint,
          closestPoint;
      return function closestPointToPoint(point, optionalTarget) {
        if (plane === undefined) {
          plane = new THREE.Plane();
          edgeList = [new THREE.Line3(), new THREE.Line3(), new THREE.Line3()];
          projectedPoint = new THREE.Vector3();
          closestPoint = new THREE.Vector3();
        }
        var result = optionalTarget || new THREE.Vector3();
        var minDistance = Infinity;
        plane.setFromCoplanarPoints(this.a, this.b, this.c);
        plane.projectPoint(point, projectedPoint);
        if (this.containsPoint(projectedPoint) === true) {
          result.copy(projectedPoint);
        } else {
          edgeList[0].set(this.a, this.b);
          edgeList[1].set(this.b, this.c);
          edgeList[2].set(this.c, this.a);
          for (var i = 0; i < edgeList.length; i++) {
            edgeList[i].closestPointToPoint(projectedPoint, true, closestPoint);
            var distance = projectedPoint.distanceToSquared(closestPoint);
            if (distance < minDistance) {
              minDistance = distance;
              result.copy(closestPoint);
            }
          }
        }
        return result;
      };
    }(),
    equals: function(triangle) {
      return triangle.a.equals(this.a) && triangle.b.equals(this.b) && triangle.c.equals(this.c);
    }
  };
  THREE.Interpolant = function(parameterPositions, sampleValues, sampleSize, resultBuffer) {
    this.parameterPositions = parameterPositions;
    this._cachedIndex = 0;
    this.resultBuffer = resultBuffer !== undefined ? resultBuffer : new sampleValues.constructor(sampleSize);
    this.sampleValues = sampleValues;
    this.valueSize = sampleSize;
  };
  THREE.Interpolant.prototype = {
    constructor: THREE.Interpolant,
    evaluate: function(t) {
      var pp = this.parameterPositions,
          i1 = this._cachedIndex,
          t1 = pp[i1],
          t0 = pp[i1 - 1];
      validate_interval: {
        seek: {
          var right;
          linear_scan: {
            forward_scan: if (!(t < t1)) {
              for (var giveUpAt = i1 + 2; ; ) {
                if (t1 === undefined) {
                  if (t < t0)
                    break forward_scan;
                  i1 = pp.length;
                  this._cachedIndex = i1;
                  return this.afterEnd_(i1 - 1, t, t0);
                }
                if (i1 === giveUpAt)
                  break;
                t0 = t1;
                t1 = pp[++i1];
                if (t < t1) {
                  break seek;
                }
              }
              right = pp.length;
              break linear_scan;
            }
            if (!(t >= t0)) {
              var t1global = pp[1];
              if (t < t1global) {
                i1 = 2;
                t0 = t1global;
              }
              for (var giveUpAt = i1 - 2; ; ) {
                if (t0 === undefined) {
                  this._cachedIndex = 0;
                  return this.beforeStart_(0, t, t1);
                }
                if (i1 === giveUpAt)
                  break;
                t1 = t0;
                t0 = pp[--i1 - 1];
                if (t >= t0) {
                  break seek;
                }
              }
              right = i1;
              i1 = 0;
              break linear_scan;
            }
            break validate_interval;
          }
          while (i1 < right) {
            var mid = (i1 + right) >>> 1;
            if (t < pp[mid]) {
              right = mid;
            } else {
              i1 = mid + 1;
            }
          }
          t1 = pp[i1];
          t0 = pp[i1 - 1];
          if (t0 === undefined) {
            this._cachedIndex = 0;
            return this.beforeStart_(0, t, t1);
          }
          if (t1 === undefined) {
            i1 = pp.length;
            this._cachedIndex = i1;
            return this.afterEnd_(i1 - 1, t0, t);
          }
        }
        this._cachedIndex = i1;
        this.intervalChanged_(i1, t0, t1);
      }
      return this.interpolate_(i1, t0, t, t1);
    },
    settings: null,
    DefaultSettings_: {},
    getSettings_: function() {
      return this.settings || this.DefaultSettings_;
    },
    copySampleValue_: function(index) {
      var result = this.resultBuffer,
          values = this.sampleValues,
          stride = this.valueSize,
          offset = index * stride;
      for (var i = 0; i !== stride; ++i) {
        result[i] = values[offset + i];
      }
      return result;
    },
    interpolate_: function(i1, t0, t, t1) {
      throw new Error("call to abstract method");
    },
    intervalChanged_: function(i1, t0, t1) {}
  };
  Object.assign(THREE.Interpolant.prototype, {
    beforeStart_: THREE.Interpolant.prototype.copySampleValue_,
    afterEnd_: THREE.Interpolant.prototype.copySampleValue_
  });
  THREE.CubicInterpolant = function(parameterPositions, sampleValues, sampleSize, resultBuffer) {
    THREE.Interpolant.call(this, parameterPositions, sampleValues, sampleSize, resultBuffer);
    this._weightPrev = -0;
    this._offsetPrev = -0;
    this._weightNext = -0;
    this._offsetNext = -0;
  };
  THREE.CubicInterpolant.prototype = Object.assign(Object.create(THREE.Interpolant.prototype), {
    constructor: THREE.CubicInterpolant,
    DefaultSettings_: {
      endingStart: THREE.ZeroCurvatureEnding,
      endingEnd: THREE.ZeroCurvatureEnding
    },
    intervalChanged_: function(i1, t0, t1) {
      var pp = this.parameterPositions,
          iPrev = i1 - 2,
          iNext = i1 + 1,
          tPrev = pp[iPrev],
          tNext = pp[iNext];
      if (tPrev === undefined) {
        switch (this.getSettings_().endingStart) {
          case THREE.ZeroSlopeEnding:
            iPrev = i1;
            tPrev = 2 * t0 - t1;
            break;
          case THREE.WrapAroundEnding:
            iPrev = pp.length - 2;
            tPrev = t0 + pp[iPrev] - pp[iPrev + 1];
            break;
          default:
            iPrev = i1;
            tPrev = t1;
        }
      }
      if (tNext === undefined) {
        switch (this.getSettings_().endingEnd) {
          case THREE.ZeroSlopeEnding:
            iNext = i1;
            tNext = 2 * t1 - t0;
            break;
          case THREE.WrapAroundEnding:
            iNext = 1;
            tNext = t1 + pp[1] - pp[0];
            break;
          default:
            iNext = i1 - 1;
            tNext = t0;
        }
      }
      var halfDt = (t1 - t0) * 0.5,
          stride = this.valueSize;
      this._weightPrev = halfDt / (t0 - tPrev);
      this._weightNext = halfDt / (tNext - t1);
      this._offsetPrev = iPrev * stride;
      this._offsetNext = iNext * stride;
    },
    interpolate_: function(i1, t0, t, t1) {
      var result = this.resultBuffer,
          values = this.sampleValues,
          stride = this.valueSize,
          o1 = i1 * stride,
          o0 = o1 - stride,
          oP = this._offsetPrev,
          oN = this._offsetNext,
          wP = this._weightPrev,
          wN = this._weightNext,
          p = (t - t0) / (t1 - t0),
          pp = p * p,
          ppp = pp * p;
      var sP = -wP * ppp + 2 * wP * pp - wP * p;
      var s0 = (1 + wP) * ppp + (-1.5 - 2 * wP) * pp + (-0.5 + wP) * p + 1;
      var s1 = (-1 - wN) * ppp + (1.5 + wN) * pp + 0.5 * p;
      var sN = wN * ppp - wN * pp;
      for (var i = 0; i !== stride; ++i) {
        result[i] = sP * values[oP + i] + s0 * values[o0 + i] + s1 * values[o1 + i] + sN * values[oN + i];
      }
      return result;
    }
  });
  THREE.DiscreteInterpolant = function(parameterPositions, sampleValues, sampleSize, resultBuffer) {
    THREE.Interpolant.call(this, parameterPositions, sampleValues, sampleSize, resultBuffer);
  };
  THREE.DiscreteInterpolant.prototype = Object.assign(Object.create(THREE.Interpolant.prototype), {
    constructor: THREE.DiscreteInterpolant,
    interpolate_: function(i1, t0, t, t1) {
      return this.copySampleValue_(i1 - 1);
    }
  });
  THREE.LinearInterpolant = function(parameterPositions, sampleValues, sampleSize, resultBuffer) {
    THREE.Interpolant.call(this, parameterPositions, sampleValues, sampleSize, resultBuffer);
  };
  THREE.LinearInterpolant.prototype = Object.assign(Object.create(THREE.Interpolant.prototype), {
    constructor: THREE.LinearInterpolant,
    interpolate_: function(i1, t0, t, t1) {
      var result = this.resultBuffer,
          values = this.sampleValues,
          stride = this.valueSize,
          offset1 = i1 * stride,
          offset0 = offset1 - stride,
          weight1 = (t - t0) / (t1 - t0),
          weight0 = 1 - weight1;
      for (var i = 0; i !== stride; ++i) {
        result[i] = values[offset0 + i] * weight0 + values[offset1 + i] * weight1;
      }
      return result;
    }
  });
  THREE.QuaternionLinearInterpolant = function(parameterPositions, sampleValues, sampleSize, resultBuffer) {
    THREE.Interpolant.call(this, parameterPositions, sampleValues, sampleSize, resultBuffer);
  };
  THREE.QuaternionLinearInterpolant.prototype = Object.assign(Object.create(THREE.Interpolant.prototype), {
    constructor: THREE.QuaternionLinearInterpolant,
    interpolate_: function(i1, t0, t, t1) {
      var result = this.resultBuffer,
          values = this.sampleValues,
          stride = this.valueSize,
          offset = i1 * stride,
          alpha = (t - t0) / (t1 - t0);
      for (var end = offset + stride; offset !== end; offset += 4) {
        THREE.Quaternion.slerpFlat(result, 0, values, offset - stride, values, offset, alpha);
      }
      return result;
    }
  });
  THREE.Clock = function(autoStart) {
    this.autoStart = (autoStart !== undefined) ? autoStart : true;
    this.startTime = 0;
    this.oldTime = 0;
    this.elapsedTime = 0;
    this.running = false;
  };
  THREE.Clock.prototype = {
    constructor: THREE.Clock,
    start: function() {
      this.startTime = (performance || Date).now();
      this.oldTime = this.startTime;
      this.running = true;
    },
    stop: function() {
      this.getElapsedTime();
      this.running = false;
    },
    getElapsedTime: function() {
      this.getDelta();
      return this.elapsedTime;
    },
    getDelta: function() {
      var diff = 0;
      if (this.autoStart && !this.running) {
        this.start();
      }
      if (this.running) {
        var newTime = (performance || Date).now();
        diff = (newTime - this.oldTime) / 1000;
        this.oldTime = newTime;
        this.elapsedTime += diff;
      }
      return diff;
    }
  };
  THREE.EventDispatcher = function() {};
  Object.assign(THREE.EventDispatcher.prototype, {
    addEventListener: function(type, listener) {
      if (this._listeners === undefined)
        this._listeners = {};
      var listeners = this._listeners;
      if (listeners[type] === undefined) {
        listeners[type] = [];
      }
      if (listeners[type].indexOf(listener) === -1) {
        listeners[type].push(listener);
      }
    },
    hasEventListener: function(type, listener) {
      if (this._listeners === undefined)
        return false;
      var listeners = this._listeners;
      if (listeners[type] !== undefined && listeners[type].indexOf(listener) !== -1) {
        return true;
      }
      return false;
    },
    removeEventListener: function(type, listener) {
      if (this._listeners === undefined)
        return;
      var listeners = this._listeners;
      var listenerArray = listeners[type];
      if (listenerArray !== undefined) {
        var index = listenerArray.indexOf(listener);
        if (index !== -1) {
          listenerArray.splice(index, 1);
        }
      }
    },
    dispatchEvent: function(event) {
      if (this._listeners === undefined)
        return;
      var listeners = this._listeners;
      var listenerArray = listeners[event.type];
      if (listenerArray !== undefined) {
        event.target = this;
        var array = [],
            i = 0;
        var length = listenerArray.length;
        for (i = 0; i < length; i++) {
          array[i] = listenerArray[i];
        }
        for (i = 0; i < length; i++) {
          array[i].call(this, event);
        }
      }
    }
  });
  THREE.Layers = function() {
    this.mask = 1;
  };
  THREE.Layers.prototype = {
    constructor: THREE.Layers,
    set: function(channel) {
      this.mask = 1 << channel;
    },
    enable: function(channel) {
      this.mask |= 1 << channel;
    },
    toggle: function(channel) {
      this.mask ^= 1 << channel;
    },
    disable: function(channel) {
      this.mask &= ~(1 << channel);
    },
    test: function(layers) {
      return (this.mask & layers.mask) !== 0;
    }
  };
  (function(THREE) {
    THREE.Raycaster = function(origin, direction, near, far) {
      this.ray = new THREE.Ray(origin, direction);
      this.near = near || 0;
      this.far = far || Infinity;
      this.params = {
        Mesh: {},
        Line: {},
        LOD: {},
        Points: {threshold: 1},
        Sprite: {}
      };
      Object.defineProperties(this.params, {PointCloud: {get: function() {
            console.warn('THREE.Raycaster: params.PointCloud has been renamed to params.Points.');
            return this.Points;
          }}});
    };
    function ascSort(a, b) {
      return a.distance - b.distance;
    }
    function intersectObject(object, raycaster, intersects, recursive) {
      if (object.visible === false)
        return;
      object.raycast(raycaster, intersects);
      if (recursive === true) {
        var children = object.children;
        for (var i = 0,
            l = children.length; i < l; i++) {
          intersectObject(children[i], raycaster, intersects, true);
        }
      }
    }
    THREE.Raycaster.prototype = {
      constructor: THREE.Raycaster,
      linePrecision: 1,
      set: function(origin, direction) {
        this.ray.set(origin, direction);
      },
      setFromCamera: function(coords, camera) {
        if (camera instanceof THREE.PerspectiveCamera) {
          this.ray.origin.setFromMatrixPosition(camera.matrixWorld);
          this.ray.direction.set(coords.x, coords.y, 0.5).unproject(camera).sub(this.ray.origin).normalize();
        } else if (camera instanceof THREE.OrthographicCamera) {
          this.ray.origin.set(coords.x, coords.y, (camera.near + camera.far) / (camera.near - camera.far)).unproject(camera);
          this.ray.direction.set(0, 0, -1).transformDirection(camera.matrixWorld);
        } else {
          console.error('THREE.Raycaster: Unsupported camera type.');
        }
      },
      intersectObject: function(object, recursive) {
        var intersects = [];
        intersectObject(object, this, intersects, recursive);
        intersects.sort(ascSort);
        return intersects;
      },
      intersectObjects: function(objects, recursive) {
        var intersects = [];
        if (Array.isArray(objects) === false) {
          console.warn('THREE.Raycaster.intersectObjects: objects is not an Array.');
          return intersects;
        }
        for (var i = 0,
            l = objects.length; i < l; i++) {
          intersectObject(objects[i], this, intersects, recursive);
        }
        intersects.sort(ascSort);
        return intersects;
      }
    };
  }(THREE));
  THREE.Object3D = function() {
    Object.defineProperty(this, 'id', {value: THREE.Object3DIdCount++});
    this.uuid = THREE.Math.generateUUID();
    this.name = '';
    this.type = 'Object3D';
    this.parent = null;
    this.children = [];
    this.up = THREE.Object3D.DefaultUp.clone();
    var position = new THREE.Vector3();
    var rotation = new THREE.Euler();
    var quaternion = new THREE.Quaternion();
    var scale = new THREE.Vector3(1, 1, 1);
    function onRotationChange() {
      quaternion.setFromEuler(rotation, false);
    }
    function onQuaternionChange() {
      rotation.setFromQuaternion(quaternion, undefined, false);
    }
    rotation.onChange(onRotationChange);
    quaternion.onChange(onQuaternionChange);
    Object.defineProperties(this, {
      position: {
        enumerable: true,
        value: position
      },
      rotation: {
        enumerable: true,
        value: rotation
      },
      quaternion: {
        enumerable: true,
        value: quaternion
      },
      scale: {
        enumerable: true,
        value: scale
      },
      modelViewMatrix: {value: new THREE.Matrix4()},
      normalMatrix: {value: new THREE.Matrix3()}
    });
    this.matrix = new THREE.Matrix4();
    this.matrixWorld = new THREE.Matrix4();
    this.matrixAutoUpdate = THREE.Object3D.DefaultMatrixAutoUpdate;
    this.matrixWorldNeedsUpdate = false;
    this.layers = new THREE.Layers();
    this.visible = true;
    this.castShadow = false;
    this.receiveShadow = false;
    this.frustumCulled = true;
    this.renderOrder = 0;
    this.userData = {};
  };
  THREE.Object3D.DefaultUp = new THREE.Vector3(0, 1, 0);
  THREE.Object3D.DefaultMatrixAutoUpdate = true;
  Object.assign(THREE.Object3D.prototype, THREE.EventDispatcher.prototype, {
    applyMatrix: function(matrix) {
      this.matrix.multiplyMatrices(matrix, this.matrix);
      this.matrix.decompose(this.position, this.quaternion, this.scale);
    },
    setRotationFromAxisAngle: function(axis, angle) {
      this.quaternion.setFromAxisAngle(axis, angle);
    },
    setRotationFromEuler: function(euler) {
      this.quaternion.setFromEuler(euler, true);
    },
    setRotationFromMatrix: function(m) {
      this.quaternion.setFromRotationMatrix(m);
    },
    setRotationFromQuaternion: function(q) {
      this.quaternion.copy(q);
    },
    rotateOnAxis: function() {
      var q1 = new THREE.Quaternion();
      return function rotateOnAxis(axis, angle) {
        q1.setFromAxisAngle(axis, angle);
        this.quaternion.multiply(q1);
        return this;
      };
    }(),
    rotateX: function() {
      var v1 = new THREE.Vector3(1, 0, 0);
      return function rotateX(angle) {
        return this.rotateOnAxis(v1, angle);
      };
    }(),
    rotateY: function() {
      var v1 = new THREE.Vector3(0, 1, 0);
      return function rotateY(angle) {
        return this.rotateOnAxis(v1, angle);
      };
    }(),
    rotateZ: function() {
      var v1 = new THREE.Vector3(0, 0, 1);
      return function rotateZ(angle) {
        return this.rotateOnAxis(v1, angle);
      };
    }(),
    translateOnAxis: function() {
      var v1 = new THREE.Vector3();
      return function translateOnAxis(axis, distance) {
        v1.copy(axis).applyQuaternion(this.quaternion);
        this.position.add(v1.multiplyScalar(distance));
        return this;
      };
    }(),
    translateX: function() {
      var v1 = new THREE.Vector3(1, 0, 0);
      return function translateX(distance) {
        return this.translateOnAxis(v1, distance);
      };
    }(),
    translateY: function() {
      var v1 = new THREE.Vector3(0, 1, 0);
      return function translateY(distance) {
        return this.translateOnAxis(v1, distance);
      };
    }(),
    translateZ: function() {
      var v1 = new THREE.Vector3(0, 0, 1);
      return function translateZ(distance) {
        return this.translateOnAxis(v1, distance);
      };
    }(),
    localToWorld: function(vector) {
      return vector.applyMatrix4(this.matrixWorld);
    },
    worldToLocal: function() {
      var m1 = new THREE.Matrix4();
      return function worldToLocal(vector) {
        return vector.applyMatrix4(m1.getInverse(this.matrixWorld));
      };
    }(),
    lookAt: function() {
      var m1 = new THREE.Matrix4();
      return function lookAt(vector) {
        m1.lookAt(vector, this.position, this.up);
        this.quaternion.setFromRotationMatrix(m1);
      };
    }(),
    add: function(object) {
      if (arguments.length > 1) {
        for (var i = 0; i < arguments.length; i++) {
          this.add(arguments[i]);
        }
        return this;
      }
      if (object === this) {
        console.error("THREE.Object3D.add: object can't be added as a child of itself.", object);
        return this;
      }
      if (object instanceof THREE.Object3D) {
        if (object.parent !== null) {
          object.parent.remove(object);
        }
        object.parent = this;
        object.dispatchEvent({type: 'added'});
        this.children.push(object);
      } else {
        console.error("THREE.Object3D.add: object not an instance of THREE.Object3D.", object);
      }
      return this;
    },
    remove: function(object) {
      if (arguments.length > 1) {
        for (var i = 0; i < arguments.length; i++) {
          this.remove(arguments[i]);
        }
      }
      var index = this.children.indexOf(object);
      if (index !== -1) {
        object.parent = null;
        object.dispatchEvent({type: 'removed'});
        this.children.splice(index, 1);
      }
    },
    getObjectById: function(id) {
      return this.getObjectByProperty('id', id);
    },
    getObjectByName: function(name) {
      return this.getObjectByProperty('name', name);
    },
    getObjectByProperty: function(name, value) {
      if (this[name] === value)
        return this;
      for (var i = 0,
          l = this.children.length; i < l; i++) {
        var child = this.children[i];
        var object = child.getObjectByProperty(name, value);
        if (object !== undefined) {
          return object;
        }
      }
      return undefined;
    },
    getWorldPosition: function(optionalTarget) {
      var result = optionalTarget || new THREE.Vector3();
      this.updateMatrixWorld(true);
      return result.setFromMatrixPosition(this.matrixWorld);
    },
    getWorldQuaternion: function() {
      var position = new THREE.Vector3();
      var scale = new THREE.Vector3();
      return function getWorldQuaternion(optionalTarget) {
        var result = optionalTarget || new THREE.Quaternion();
        this.updateMatrixWorld(true);
        this.matrixWorld.decompose(position, result, scale);
        return result;
      };
    }(),
    getWorldRotation: function() {
      var quaternion = new THREE.Quaternion();
      return function getWorldRotation(optionalTarget) {
        var result = optionalTarget || new THREE.Euler();
        this.getWorldQuaternion(quaternion);
        return result.setFromQuaternion(quaternion, this.rotation.order, false);
      };
    }(),
    getWorldScale: function() {
      var position = new THREE.Vector3();
      var quaternion = new THREE.Quaternion();
      return function getWorldScale(optionalTarget) {
        var result = optionalTarget || new THREE.Vector3();
        this.updateMatrixWorld(true);
        this.matrixWorld.decompose(position, quaternion, result);
        return result;
      };
    }(),
    getWorldDirection: function() {
      var quaternion = new THREE.Quaternion();
      return function getWorldDirection(optionalTarget) {
        var result = optionalTarget || new THREE.Vector3();
        this.getWorldQuaternion(quaternion);
        return result.set(0, 0, 1).applyQuaternion(quaternion);
      };
    }(),
    raycast: function() {},
    traverse: function(callback) {
      callback(this);
      var children = this.children;
      for (var i = 0,
          l = children.length; i < l; i++) {
        children[i].traverse(callback);
      }
    },
    traverseVisible: function(callback) {
      if (this.visible === false)
        return;
      callback(this);
      var children = this.children;
      for (var i = 0,
          l = children.length; i < l; i++) {
        children[i].traverseVisible(callback);
      }
    },
    traverseAncestors: function(callback) {
      var parent = this.parent;
      if (parent !== null) {
        callback(parent);
        parent.traverseAncestors(callback);
      }
    },
    updateMatrix: function() {
      this.matrix.compose(this.position, this.quaternion, this.scale);
      this.matrixWorldNeedsUpdate = true;
    },
    updateMatrixWorld: function(force) {
      if (this.matrixAutoUpdate === true)
        this.updateMatrix();
      if (this.matrixWorldNeedsUpdate === true || force === true) {
        if (this.parent === null) {
          this.matrixWorld.copy(this.matrix);
        } else {
          this.matrixWorld.multiplyMatrices(this.parent.matrixWorld, this.matrix);
        }
        this.matrixWorldNeedsUpdate = false;
        force = true;
      }
      for (var i = 0,
          l = this.children.length; i < l; i++) {
        this.children[i].updateMatrixWorld(force);
      }
    },
    toJSON: function(meta) {
      var isRootObject = (meta === undefined || meta === '');
      var output = {};
      if (isRootObject) {
        meta = {
          geometries: {},
          materials: {},
          textures: {},
          images: {}
        };
        output.metadata = {
          version: 4.4,
          type: 'Object',
          generator: 'Object3D.toJSON'
        };
      }
      var object = {};
      object.uuid = this.uuid;
      object.type = this.type;
      if (this.name !== '')
        object.name = this.name;
      if (JSON.stringify(this.userData) !== '{}')
        object.userData = this.userData;
      if (this.castShadow === true)
        object.castShadow = true;
      if (this.receiveShadow === true)
        object.receiveShadow = true;
      if (this.visible === false)
        object.visible = false;
      object.matrix = this.matrix.toArray();
      if (this.geometry !== undefined) {
        if (meta.geometries[this.geometry.uuid] === undefined) {
          meta.geometries[this.geometry.uuid] = this.geometry.toJSON(meta);
        }
        object.geometry = this.geometry.uuid;
      }
      if (this.material !== undefined) {
        if (meta.materials[this.material.uuid] === undefined) {
          meta.materials[this.material.uuid] = this.material.toJSON(meta);
        }
        object.material = this.material.uuid;
      }
      if (this.children.length > 0) {
        object.children = [];
        for (var i = 0; i < this.children.length; i++) {
          object.children.push(this.children[i].toJSON(meta).object);
        }
      }
      if (isRootObject) {
        var geometries = extractFromCache(meta.geometries);
        var materials = extractFromCache(meta.materials);
        var textures = extractFromCache(meta.textures);
        var images = extractFromCache(meta.images);
        if (geometries.length > 0)
          output.geometries = geometries;
        if (materials.length > 0)
          output.materials = materials;
        if (textures.length > 0)
          output.textures = textures;
        if (images.length > 0)
          output.images = images;
      }
      output.object = object;
      return output;
      function extractFromCache(cache) {
        var values = [];
        for (var key in cache) {
          var data = cache[key];
          delete data.metadata;
          values.push(data);
        }
        return values;
      }
    },
    clone: function(recursive) {
      return new this.constructor().copy(this, recursive);
    },
    copy: function(source, recursive) {
      if (recursive === undefined)
        recursive = true;
      this.name = source.name;
      this.up.copy(source.up);
      this.position.copy(source.position);
      this.quaternion.copy(source.quaternion);
      this.scale.copy(source.scale);
      this.matrix.copy(source.matrix);
      this.matrixWorld.copy(source.matrixWorld);
      this.matrixAutoUpdate = source.matrixAutoUpdate;
      this.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate;
      this.visible = source.visible;
      this.castShadow = source.castShadow;
      this.receiveShadow = source.receiveShadow;
      this.frustumCulled = source.frustumCulled;
      this.renderOrder = source.renderOrder;
      this.userData = JSON.parse(JSON.stringify(source.userData));
      if (recursive === true) {
        for (var i = 0; i < source.children.length; i++) {
          var child = source.children[i];
          this.add(child.clone());
        }
      }
      return this;
    }
  });
  THREE.Object3DIdCount = 0;
  THREE.Face3 = function(a, b, c, normal, color, materialIndex) {
    this.a = a;
    this.b = b;
    this.c = c;
    this.normal = normal instanceof THREE.Vector3 ? normal : new THREE.Vector3();
    this.vertexNormals = Array.isArray(normal) ? normal : [];
    this.color = color instanceof THREE.Color ? color : new THREE.Color();
    this.vertexColors = Array.isArray(color) ? color : [];
    this.materialIndex = materialIndex !== undefined ? materialIndex : 0;
  };
  THREE.Face3.prototype = {
    constructor: THREE.Face3,
    clone: function() {
      return new this.constructor().copy(this);
    },
    copy: function(source) {
      this.a = source.a;
      this.b = source.b;
      this.c = source.c;
      this.normal.copy(source.normal);
      this.color.copy(source.color);
      this.materialIndex = source.materialIndex;
      for (var i = 0,
          il = source.vertexNormals.length; i < il; i++) {
        this.vertexNormals[i] = source.vertexNormals[i].clone();
      }
      for (var i = 0,
          il = source.vertexColors.length; i < il; i++) {
        this.vertexColors[i] = source.vertexColors[i].clone();
      }
      return this;
    }
  };
  THREE.BufferAttribute = function(array, itemSize, normalized) {
    this.uuid = THREE.Math.generateUUID();
    this.array = array;
    this.itemSize = itemSize;
    this.dynamic = false;
    this.updateRange = {
      offset: 0,
      count: -1
    };
    this.version = 0;
    this.normalized = normalized === true;
  };
  THREE.BufferAttribute.prototype = {
    constructor: THREE.BufferAttribute,
    get count() {
      return this.array.length / this.itemSize;
    },
    set needsUpdate(value) {
      if (value === true)
        this.version++;
    },
    setDynamic: function(value) {
      this.dynamic = value;
      return this;
    },
    copy: function(source) {
      this.array = new source.array.constructor(source.array);
      this.itemSize = source.itemSize;
      this.dynamic = source.dynamic;
      return this;
    },
    copyAt: function(index1, attribute, index2) {
      index1 *= this.itemSize;
      index2 *= attribute.itemSize;
      for (var i = 0,
          l = this.itemSize; i < l; i++) {
        this.array[index1 + i] = attribute.array[index2 + i];
      }
      return this;
    },
    copyArray: function(array) {
      this.array.set(array);
      return this;
    },
    copyColorsArray: function(colors) {
      var array = this.array,
          offset = 0;
      for (var i = 0,
          l = colors.length; i < l; i++) {
        var color = colors[i];
        if (color === undefined) {
          console.warn('THREE.BufferAttribute.copyColorsArray(): color is undefined', i);
          color = new THREE.Color();
        }
        array[offset++] = color.r;
        array[offset++] = color.g;
        array[offset++] = color.b;
      }
      return this;
    },
    copyIndicesArray: function(indices) {
      var array = this.array,
          offset = 0;
      for (var i = 0,
          l = indices.length; i < l; i++) {
        var index = indices[i];
        array[offset++] = index.a;
        array[offset++] = index.b;
        array[offset++] = index.c;
      }
      return this;
    },
    copyVector2sArray: function(vectors) {
      var array = this.array,
          offset = 0;
      for (var i = 0,
          l = vectors.length; i < l; i++) {
        var vector = vectors[i];
        if (vector === undefined) {
          console.warn('THREE.BufferAttribute.copyVector2sArray(): vector is undefined', i);
          vector = new THREE.Vector2();
        }
        array[offset++] = vector.x;
        array[offset++] = vector.y;
      }
      return this;
    },
    copyVector3sArray: function(vectors) {
      var array = this.array,
          offset = 0;
      for (var i = 0,
          l = vectors.length; i < l; i++) {
        var vector = vectors[i];
        if (vector === undefined) {
          console.warn('THREE.BufferAttribute.copyVector3sArray(): vector is undefined', i);
          vector = new THREE.Vector3();
        }
        array[offset++] = vector.x;
        array[offset++] = vector.y;
        array[offset++] = vector.z;
      }
      return this;
    },
    copyVector4sArray: function(vectors) {
      var array = this.array,
          offset = 0;
      for (var i = 0,
          l = vectors.length; i < l; i++) {
        var vector = vectors[i];
        if (vector === undefined) {
          console.warn('THREE.BufferAttribute.copyVector4sArray(): vector is undefined', i);
          vector = new THREE.Vector4();
        }
        array[offset++] = vector.x;
        array[offset++] = vector.y;
        array[offset++] = vector.z;
        array[offset++] = vector.w;
      }
      return this;
    },
    set: function(value, offset) {
      if (offset === undefined)
        offset = 0;
      this.array.set(value, offset);
      return this;
    },
    getX: function(index) {
      return this.array[index * this.itemSize];
    },
    setX: function(index, x) {
      this.array[index * this.itemSize] = x;
      return this;
    },
    getY: function(index) {
      return this.array[index * this.itemSize + 1];
    },
    setY: function(index, y) {
      this.array[index * this.itemSize + 1] = y;
      return this;
    },
    getZ: function(index) {
      return this.array[index * this.itemSize + 2];
    },
    setZ: function(index, z) {
      this.array[index * this.itemSize + 2] = z;
      return this;
    },
    getW: function(index) {
      return this.array[index * this.itemSize + 3];
    },
    setW: function(index, w) {
      this.array[index * this.itemSize + 3] = w;
      return this;
    },
    setXY: function(index, x, y) {
      index *= this.itemSize;
      this.array[index + 0] = x;
      this.array[index + 1] = y;
      return this;
    },
    setXYZ: function(index, x, y, z) {
      index *= this.itemSize;
      this.array[index + 0] = x;
      this.array[index + 1] = y;
      this.array[index + 2] = z;
      return this;
    },
    setXYZW: function(index, x, y, z, w) {
      index *= this.itemSize;
      this.array[index + 0] = x;
      this.array[index + 1] = y;
      this.array[index + 2] = z;
      this.array[index + 3] = w;
      return this;
    },
    clone: function() {
      return new this.constructor().copy(this);
    }
  };
  THREE.Int8Attribute = function(array, itemSize) {
    return new THREE.BufferAttribute(new Int8Array(array), itemSize);
  };
  THREE.Uint8Attribute = function(array, itemSize) {
    return new THREE.BufferAttribute(new Uint8Array(array), itemSize);
  };
  THREE.Uint8ClampedAttribute = function(array, itemSize) {
    return new THREE.BufferAttribute(new Uint8ClampedArray(array), itemSize);
  };
  THREE.Int16Attribute = function(array, itemSize) {
    return new THREE.BufferAttribute(new Int16Array(array), itemSize);
  };
  THREE.Uint16Attribute = function(array, itemSize) {
    return new THREE.BufferAttribute(new Uint16Array(array), itemSize);
  };
  THREE.Int32Attribute = function(array, itemSize) {
    return new THREE.BufferAttribute(new Int32Array(array), itemSize);
  };
  THREE.Uint32Attribute = function(array, itemSize) {
    return new THREE.BufferAttribute(new Uint32Array(array), itemSize);
  };
  THREE.Float32Attribute = function(array, itemSize) {
    return new THREE.BufferAttribute(new Float32Array(array), itemSize);
  };
  THREE.Float64Attribute = function(array, itemSize) {
    return new THREE.BufferAttribute(new Float64Array(array), itemSize);
  };
  THREE.DynamicBufferAttribute = function(array, itemSize) {
    console.warn('THREE.DynamicBufferAttribute has been removed. Use new THREE.BufferAttribute().setDynamic( true ) instead.');
    return new THREE.BufferAttribute(array, itemSize).setDynamic(true);
  };
  THREE.InstancedBufferAttribute = function(array, itemSize, meshPerAttribute) {
    THREE.BufferAttribute.call(this, array, itemSize);
    this.meshPerAttribute = meshPerAttribute || 1;
  };
  THREE.InstancedBufferAttribute.prototype = Object.create(THREE.BufferAttribute.prototype);
  THREE.InstancedBufferAttribute.prototype.constructor = THREE.InstancedBufferAttribute;
  THREE.InstancedBufferAttribute.prototype.copy = function(source) {
    THREE.BufferAttribute.prototype.copy.call(this, source);
    this.meshPerAttribute = source.meshPerAttribute;
    return this;
  };
  THREE.InterleavedBuffer = function(array, stride) {
    this.uuid = THREE.Math.generateUUID();
    this.array = array;
    this.stride = stride;
    this.dynamic = false;
    this.updateRange = {
      offset: 0,
      count: -1
    };
    this.version = 0;
  };
  THREE.InterleavedBuffer.prototype = {
    constructor: THREE.InterleavedBuffer,
    get length() {
      return this.array.length;
    },
    get count() {
      return this.array.length / this.stride;
    },
    set needsUpdate(value) {
      if (value === true)
        this.version++;
    },
    setDynamic: function(value) {
      this.dynamic = value;
      return this;
    },
    copy: function(source) {
      this.array = new source.array.constructor(source.array);
      this.stride = source.stride;
      this.dynamic = source.dynamic;
      return this;
    },
    copyAt: function(index1, attribute, index2) {
      index1 *= this.stride;
      index2 *= attribute.stride;
      for (var i = 0,
          l = this.stride; i < l; i++) {
        this.array[index1 + i] = attribute.array[index2 + i];
      }
      return this;
    },
    set: function(value, offset) {
      if (offset === undefined)
        offset = 0;
      this.array.set(value, offset);
      return this;
    },
    clone: function() {
      return new this.constructor().copy(this);
    }
  };
  THREE.InstancedInterleavedBuffer = function(array, stride, meshPerAttribute) {
    THREE.InterleavedBuffer.call(this, array, stride);
    this.meshPerAttribute = meshPerAttribute || 1;
  };
  THREE.InstancedInterleavedBuffer.prototype = Object.create(THREE.InterleavedBuffer.prototype);
  THREE.InstancedInterleavedBuffer.prototype.constructor = THREE.InstancedInterleavedBuffer;
  THREE.InstancedInterleavedBuffer.prototype.copy = function(source) {
    THREE.InterleavedBuffer.prototype.copy.call(this, source);
    this.meshPerAttribute = source.meshPerAttribute;
    return this;
  };
  THREE.InterleavedBufferAttribute = function(interleavedBuffer, itemSize, offset) {
    this.uuid = THREE.Math.generateUUID();
    this.data = interleavedBuffer;
    this.itemSize = itemSize;
    this.offset = offset;
  };
  THREE.InterleavedBufferAttribute.prototype = {
    constructor: THREE.InterleavedBufferAttribute,
    get length() {
      console.warn('THREE.BufferAttribute: .length has been deprecated. Please use .count.');
      return this.array.length;
    },
    get count() {
      return this.data.count;
    },
    setX: function(index, x) {
      this.data.array[index * this.data.stride + this.offset] = x;
      return this;
    },
    setY: function(index, y) {
      this.data.array[index * this.data.stride + this.offset + 1] = y;
      return this;
    },
    setZ: function(index, z) {
      this.data.array[index * this.data.stride + this.offset + 2] = z;
      return this;
    },
    setW: function(index, w) {
      this.data.array[index * this.data.stride + this.offset + 3] = w;
      return this;
    },
    getX: function(index) {
      return this.data.array[index * this.data.stride + this.offset];
    },
    getY: function(index) {
      return this.data.array[index * this.data.stride + this.offset + 1];
    },
    getZ: function(index) {
      return this.data.array[index * this.data.stride + this.offset + 2];
    },
    getW: function(index) {
      return this.data.array[index * this.data.stride + this.offset + 3];
    },
    setXY: function(index, x, y) {
      index = index * this.data.stride + this.offset;
      this.data.array[index + 0] = x;
      this.data.array[index + 1] = y;
      return this;
    },
    setXYZ: function(index, x, y, z) {
      index = index * this.data.stride + this.offset;
      this.data.array[index + 0] = x;
      this.data.array[index + 1] = y;
      this.data.array[index + 2] = z;
      return this;
    },
    setXYZW: function(index, x, y, z, w) {
      index = index * this.data.stride + this.offset;
      this.data.array[index + 0] = x;
      this.data.array[index + 1] = y;
      this.data.array[index + 2] = z;
      this.data.array[index + 3] = w;
      return this;
    }
  };
  THREE.Geometry = function() {
    Object.defineProperty(this, 'id', {value: THREE.GeometryIdCount++});
    this.uuid = THREE.Math.generateUUID();
    this.name = '';
    this.type = 'Geometry';
    this.vertices = [];
    this.colors = [];
    this.faces = [];
    this.faceVertexUvs = [[]];
    this.morphTargets = [];
    this.morphNormals = [];
    this.skinWeights = [];
    this.skinIndices = [];
    this.lineDistances = [];
    this.boundingBox = null;
    this.boundingSphere = null;
    this.verticesNeedUpdate = false;
    this.elementsNeedUpdate = false;
    this.uvsNeedUpdate = false;
    this.normalsNeedUpdate = false;
    this.colorsNeedUpdate = false;
    this.lineDistancesNeedUpdate = false;
    this.groupsNeedUpdate = false;
  };
  Object.assign(THREE.Geometry.prototype, THREE.EventDispatcher.prototype, {
    applyMatrix: function(matrix) {
      var normalMatrix = new THREE.Matrix3().getNormalMatrix(matrix);
      for (var i = 0,
          il = this.vertices.length; i < il; i++) {
        var vertex = this.vertices[i];
        vertex.applyMatrix4(matrix);
      }
      for (var i = 0,
          il = this.faces.length; i < il; i++) {
        var face = this.faces[i];
        face.normal.applyMatrix3(normalMatrix).normalize();
        for (var j = 0,
            jl = face.vertexNormals.length; j < jl; j++) {
          face.vertexNormals[j].applyMatrix3(normalMatrix).normalize();
        }
      }
      if (this.boundingBox !== null) {
        this.computeBoundingBox();
      }
      if (this.boundingSphere !== null) {
        this.computeBoundingSphere();
      }
      this.verticesNeedUpdate = true;
      this.normalsNeedUpdate = true;
      return this;
    },
    rotateX: function() {
      var m1;
      return function rotateX(angle) {
        if (m1 === undefined)
          m1 = new THREE.Matrix4();
        m1.makeRotationX(angle);
        this.applyMatrix(m1);
        return this;
      };
    }(),
    rotateY: function() {
      var m1;
      return function rotateY(angle) {
        if (m1 === undefined)
          m1 = new THREE.Matrix4();
        m1.makeRotationY(angle);
        this.applyMatrix(m1);
        return this;
      };
    }(),
    rotateZ: function() {
      var m1;
      return function rotateZ(angle) {
        if (m1 === undefined)
          m1 = new THREE.Matrix4();
        m1.makeRotationZ(angle);
        this.applyMatrix(m1);
        return this;
      };
    }(),
    translate: function() {
      var m1;
      return function translate(x, y, z) {
        if (m1 === undefined)
          m1 = new THREE.Matrix4();
        m1.makeTranslation(x, y, z);
        this.applyMatrix(m1);
        return this;
      };
    }(),
    scale: function() {
      var m1;
      return function scale(x, y, z) {
        if (m1 === undefined)
          m1 = new THREE.Matrix4();
        m1.makeScale(x, y, z);
        this.applyMatrix(m1);
        return this;
      };
    }(),
    lookAt: function() {
      var obj;
      return function lookAt(vector) {
        if (obj === undefined)
          obj = new THREE.Object3D();
        obj.lookAt(vector);
        obj.updateMatrix();
        this.applyMatrix(obj.matrix);
      };
    }(),
    fromBufferGeometry: function(geometry) {
      var scope = this;
      var indices = geometry.index !== null ? geometry.index.array : undefined;
      var attributes = geometry.attributes;
      var positions = attributes.position.array;
      var normals = attributes.normal !== undefined ? attributes.normal.array : undefined;
      var colors = attributes.color !== undefined ? attributes.color.array : undefined;
      var uvs = attributes.uv !== undefined ? attributes.uv.array : undefined;
      var uvs2 = attributes.uv2 !== undefined ? attributes.uv2.array : undefined;
      if (uvs2 !== undefined)
        this.faceVertexUvs[1] = [];
      var tempNormals = [];
      var tempUVs = [];
      var tempUVs2 = [];
      for (var i = 0,
          j = 0; i < positions.length; i += 3, j += 2) {
        scope.vertices.push(new THREE.Vector3(positions[i], positions[i + 1], positions[i + 2]));
        if (normals !== undefined) {
          tempNormals.push(new THREE.Vector3(normals[i], normals[i + 1], normals[i + 2]));
        }
        if (colors !== undefined) {
          scope.colors.push(new THREE.Color(colors[i], colors[i + 1], colors[i + 2]));
        }
        if (uvs !== undefined) {
          tempUVs.push(new THREE.Vector2(uvs[j], uvs[j + 1]));
        }
        if (uvs2 !== undefined) {
          tempUVs2.push(new THREE.Vector2(uvs2[j], uvs2[j + 1]));
        }
      }
      function addFace(a, b, c, materialIndex) {
        var vertexNormals = normals !== undefined ? [tempNormals[a].clone(), tempNormals[b].clone(), tempNormals[c].clone()] : [];
        var vertexColors = colors !== undefined ? [scope.colors[a].clone(), scope.colors[b].clone(), scope.colors[c].clone()] : [];
        var face = new THREE.Face3(a, b, c, vertexNormals, vertexColors, materialIndex);
        scope.faces.push(face);
        if (uvs !== undefined) {
          scope.faceVertexUvs[0].push([tempUVs[a].clone(), tempUVs[b].clone(), tempUVs[c].clone()]);
        }
        if (uvs2 !== undefined) {
          scope.faceVertexUvs[1].push([tempUVs2[a].clone(), tempUVs2[b].clone(), tempUVs2[c].clone()]);
        }
      }
      if (indices !== undefined) {
        var groups = geometry.groups;
        if (groups.length > 0) {
          for (var i = 0; i < groups.length; i++) {
            var group = groups[i];
            var start = group.start;
            var count = group.count;
            for (var j = start,
                jl = start + count; j < jl; j += 3) {
              addFace(indices[j], indices[j + 1], indices[j + 2], group.materialIndex);
            }
          }
        } else {
          for (var i = 0; i < indices.length; i += 3) {
            addFace(indices[i], indices[i + 1], indices[i + 2]);
          }
        }
      } else {
        for (var i = 0; i < positions.length / 3; i += 3) {
          addFace(i, i + 1, i + 2);
        }
      }
      this.computeFaceNormals();
      if (geometry.boundingBox !== null) {
        this.boundingBox = geometry.boundingBox.clone();
      }
      if (geometry.boundingSphere !== null) {
        this.boundingSphere = geometry.boundingSphere.clone();
      }
      return this;
    },
    center: function() {
      this.computeBoundingBox();
      var offset = this.boundingBox.center().negate();
      this.translate(offset.x, offset.y, offset.z);
      return offset;
    },
    normalize: function() {
      this.computeBoundingSphere();
      var center = this.boundingSphere.center;
      var radius = this.boundingSphere.radius;
      var s = radius === 0 ? 1 : 1.0 / radius;
      var matrix = new THREE.Matrix4();
      matrix.set(s, 0, 0, -s * center.x, 0, s, 0, -s * center.y, 0, 0, s, -s * center.z, 0, 0, 0, 1);
      this.applyMatrix(matrix);
      return this;
    },
    computeFaceNormals: function() {
      var cb = new THREE.Vector3(),
          ab = new THREE.Vector3();
      for (var f = 0,
          fl = this.faces.length; f < fl; f++) {
        var face = this.faces[f];
        var vA = this.vertices[face.a];
        var vB = this.vertices[face.b];
        var vC = this.vertices[face.c];
        cb.subVectors(vC, vB);
        ab.subVectors(vA, vB);
        cb.cross(ab);
        cb.normalize();
        face.normal.copy(cb);
      }
    },
    computeVertexNormals: function(areaWeighted) {
      if (areaWeighted === undefined)
        areaWeighted = true;
      var v,
          vl,
          f,
          fl,
          face,
          vertices;
      vertices = new Array(this.vertices.length);
      for (v = 0, vl = this.vertices.length; v < vl; v++) {
        vertices[v] = new THREE.Vector3();
      }
      if (areaWeighted) {
        var vA,
            vB,
            vC;
        var cb = new THREE.Vector3(),
            ab = new THREE.Vector3();
        for (f = 0, fl = this.faces.length; f < fl; f++) {
          face = this.faces[f];
          vA = this.vertices[face.a];
          vB = this.vertices[face.b];
          vC = this.vertices[face.c];
          cb.subVectors(vC, vB);
          ab.subVectors(vA, vB);
          cb.cross(ab);
          vertices[face.a].add(cb);
          vertices[face.b].add(cb);
          vertices[face.c].add(cb);
        }
      } else {
        for (f = 0, fl = this.faces.length; f < fl; f++) {
          face = this.faces[f];
          vertices[face.a].add(face.normal);
          vertices[face.b].add(face.normal);
          vertices[face.c].add(face.normal);
        }
      }
      for (v = 0, vl = this.vertices.length; v < vl; v++) {
        vertices[v].normalize();
      }
      for (f = 0, fl = this.faces.length; f < fl; f++) {
        face = this.faces[f];
        var vertexNormals = face.vertexNormals;
        if (vertexNormals.length === 3) {
          vertexNormals[0].copy(vertices[face.a]);
          vertexNormals[1].copy(vertices[face.b]);
          vertexNormals[2].copy(vertices[face.c]);
        } else {
          vertexNormals[0] = vertices[face.a].clone();
          vertexNormals[1] = vertices[face.b].clone();
          vertexNormals[2] = vertices[face.c].clone();
        }
      }
      if (this.faces.length > 0) {
        this.normalsNeedUpdate = true;
      }
    },
    computeMorphNormals: function() {
      var i,
          il,
          f,
          fl,
          face;
      for (f = 0, fl = this.faces.length; f < fl; f++) {
        face = this.faces[f];
        if (!face.__originalFaceNormal) {
          face.__originalFaceNormal = face.normal.clone();
        } else {
          face.__originalFaceNormal.copy(face.normal);
        }
        if (!face.__originalVertexNormals)
          face.__originalVertexNormals = [];
        for (i = 0, il = face.vertexNormals.length; i < il; i++) {
          if (!face.__originalVertexNormals[i]) {
            face.__originalVertexNormals[i] = face.vertexNormals[i].clone();
          } else {
            face.__originalVertexNormals[i].copy(face.vertexNormals[i]);
          }
        }
      }
      var tmpGeo = new THREE.Geometry();
      tmpGeo.faces = this.faces;
      for (i = 0, il = this.morphTargets.length; i < il; i++) {
        if (!this.morphNormals[i]) {
          this.morphNormals[i] = {};
          this.morphNormals[i].faceNormals = [];
          this.morphNormals[i].vertexNormals = [];
          var dstNormalsFace = this.morphNormals[i].faceNormals;
          var dstNormalsVertex = this.morphNormals[i].vertexNormals;
          var faceNormal,
              vertexNormals;
          for (f = 0, fl = this.faces.length; f < fl; f++) {
            faceNormal = new THREE.Vector3();
            vertexNormals = {
              a: new THREE.Vector3(),
              b: new THREE.Vector3(),
              c: new THREE.Vector3()
            };
            dstNormalsFace.push(faceNormal);
            dstNormalsVertex.push(vertexNormals);
          }
        }
        var morphNormals = this.morphNormals[i];
        tmpGeo.vertices = this.morphTargets[i].vertices;
        tmpGeo.computeFaceNormals();
        tmpGeo.computeVertexNormals();
        var faceNormal,
            vertexNormals;
        for (f = 0, fl = this.faces.length; f < fl; f++) {
          face = this.faces[f];
          faceNormal = morphNormals.faceNormals[f];
          vertexNormals = morphNormals.vertexNormals[f];
          faceNormal.copy(face.normal);
          vertexNormals.a.copy(face.vertexNormals[0]);
          vertexNormals.b.copy(face.vertexNormals[1]);
          vertexNormals.c.copy(face.vertexNormals[2]);
        }
      }
      for (f = 0, fl = this.faces.length; f < fl; f++) {
        face = this.faces[f];
        face.normal = face.__originalFaceNormal;
        face.vertexNormals = face.__originalVertexNormals;
      }
    },
    computeTangents: function() {
      console.warn('THREE.Geometry: .computeTangents() has been removed.');
    },
    computeLineDistances: function() {
      var d = 0;
      var vertices = this.vertices;
      for (var i = 0,
          il = vertices.length; i < il; i++) {
        if (i > 0) {
          d += vertices[i].distanceTo(vertices[i - 1]);
        }
        this.lineDistances[i] = d;
      }
    },
    computeBoundingBox: function() {
      if (this.boundingBox === null) {
        this.boundingBox = new THREE.Box3();
      }
      this.boundingBox.setFromPoints(this.vertices);
    },
    computeBoundingSphere: function() {
      if (this.boundingSphere === null) {
        this.boundingSphere = new THREE.Sphere();
      }
      this.boundingSphere.setFromPoints(this.vertices);
    },
    merge: function(geometry, matrix, materialIndexOffset) {
      if (geometry instanceof THREE.Geometry === false) {
        console.error('THREE.Geometry.merge(): geometry not an instance of THREE.Geometry.', geometry);
        return;
      }
      var normalMatrix,
          vertexOffset = this.vertices.length,
          vertices1 = this.vertices,
          vertices2 = geometry.vertices,
          faces1 = this.faces,
          faces2 = geometry.faces,
          uvs1 = this.faceVertexUvs[0],
          uvs2 = geometry.faceVertexUvs[0];
      if (materialIndexOffset === undefined)
        materialIndexOffset = 0;
      if (matrix !== undefined) {
        normalMatrix = new THREE.Matrix3().getNormalMatrix(matrix);
      }
      for (var i = 0,
          il = vertices2.length; i < il; i++) {
        var vertex = vertices2[i];
        var vertexCopy = vertex.clone();
        if (matrix !== undefined)
          vertexCopy.applyMatrix4(matrix);
        vertices1.push(vertexCopy);
      }
      for (i = 0, il = faces2.length; i < il; i++) {
        var face = faces2[i],
            faceCopy,
            normal,
            color,
            faceVertexNormals = face.vertexNormals,
            faceVertexColors = face.vertexColors;
        faceCopy = new THREE.Face3(face.a + vertexOffset, face.b + vertexOffset, face.c + vertexOffset);
        faceCopy.normal.copy(face.normal);
        if (normalMatrix !== undefined) {
          faceCopy.normal.applyMatrix3(normalMatrix).normalize();
        }
        for (var j = 0,
            jl = faceVertexNormals.length; j < jl; j++) {
          normal = faceVertexNormals[j].clone();
          if (normalMatrix !== undefined) {
            normal.applyMatrix3(normalMatrix).normalize();
          }
          faceCopy.vertexNormals.push(normal);
        }
        faceCopy.color.copy(face.color);
        for (var j = 0,
            jl = faceVertexColors.length; j < jl; j++) {
          color = faceVertexColors[j];
          faceCopy.vertexColors.push(color.clone());
        }
        faceCopy.materialIndex = face.materialIndex + materialIndexOffset;
        faces1.push(faceCopy);
      }
      for (i = 0, il = uvs2.length; i < il; i++) {
        var uv = uvs2[i],
            uvCopy = [];
        if (uv === undefined) {
          continue;
        }
        for (var j = 0,
            jl = uv.length; j < jl; j++) {
          uvCopy.push(uv[j].clone());
        }
        uvs1.push(uvCopy);
      }
    },
    mergeMesh: function(mesh) {
      if (mesh instanceof THREE.Mesh === false) {
        console.error('THREE.Geometry.mergeMesh(): mesh not an instance of THREE.Mesh.', mesh);
        return;
      }
      mesh.matrixAutoUpdate && mesh.updateMatrix();
      this.merge(mesh.geometry, mesh.matrix);
    },
    mergeVertices: function() {
      var verticesMap = {};
      var unique = [],
          changes = [];
      var v,
          key;
      var precisionPoints = 4;
      var precision = Math.pow(10, precisionPoints);
      var i,
          il,
          face;
      var indices,
          j,
          jl;
      for (i = 0, il = this.vertices.length; i < il; i++) {
        v = this.vertices[i];
        key = Math.round(v.x * precision) + '_' + Math.round(v.y * precision) + '_' + Math.round(v.z * precision);
        if (verticesMap[key] === undefined) {
          verticesMap[key] = i;
          unique.push(this.vertices[i]);
          changes[i] = unique.length - 1;
        } else {
          changes[i] = changes[verticesMap[key]];
        }
      }
      var faceIndicesToRemove = [];
      for (i = 0, il = this.faces.length; i < il; i++) {
        face = this.faces[i];
        face.a = changes[face.a];
        face.b = changes[face.b];
        face.c = changes[face.c];
        indices = [face.a, face.b, face.c];
        var dupIndex = -1;
        for (var n = 0; n < 3; n++) {
          if (indices[n] === indices[(n + 1) % 3]) {
            dupIndex = n;
            faceIndicesToRemove.push(i);
            break;
          }
        }
      }
      for (i = faceIndicesToRemove.length - 1; i >= 0; i--) {
        var idx = faceIndicesToRemove[i];
        this.faces.splice(idx, 1);
        for (j = 0, jl = this.faceVertexUvs.length; j < jl; j++) {
          this.faceVertexUvs[j].splice(idx, 1);
        }
      }
      var diff = this.vertices.length - unique.length;
      this.vertices = unique;
      return diff;
    },
    sortFacesByMaterialIndex: function() {
      var faces = this.faces;
      var length = faces.length;
      for (var i = 0; i < length; i++) {
        faces[i]._id = i;
      }
      function materialIndexSort(a, b) {
        return a.materialIndex - b.materialIndex;
      }
      faces.sort(materialIndexSort);
      var uvs1 = this.faceVertexUvs[0];
      var uvs2 = this.faceVertexUvs[1];
      var newUvs1,
          newUvs2;
      if (uvs1 && uvs1.length === length)
        newUvs1 = [];
      if (uvs2 && uvs2.length === length)
        newUvs2 = [];
      for (var i = 0; i < length; i++) {
        var id = faces[i]._id;
        if (newUvs1)
          newUvs1.push(uvs1[id]);
        if (newUvs2)
          newUvs2.push(uvs2[id]);
      }
      if (newUvs1)
        this.faceVertexUvs[0] = newUvs1;
      if (newUvs2)
        this.faceVertexUvs[1] = newUvs2;
    },
    toJSON: function() {
      var data = {metadata: {
          version: 4.4,
          type: 'Geometry',
          generator: 'Geometry.toJSON'
        }};
      data.uuid = this.uuid;
      data.type = this.type;
      if (this.name !== '')
        data.name = this.name;
      if (this.parameters !== undefined) {
        var parameters = this.parameters;
        for (var key in parameters) {
          if (parameters[key] !== undefined)
            data[key] = parameters[key];
        }
        return data;
      }
      var vertices = [];
      for (var i = 0; i < this.vertices.length; i++) {
        var vertex = this.vertices[i];
        vertices.push(vertex.x, vertex.y, vertex.z);
      }
      var faces = [];
      var normals = [];
      var normalsHash = {};
      var colors = [];
      var colorsHash = {};
      var uvs = [];
      var uvsHash = {};
      for (var i = 0; i < this.faces.length; i++) {
        var face = this.faces[i];
        var hasMaterial = true;
        var hasFaceUv = false;
        var hasFaceVertexUv = this.faceVertexUvs[0][i] !== undefined;
        var hasFaceNormal = face.normal.length() > 0;
        var hasFaceVertexNormal = face.vertexNormals.length > 0;
        var hasFaceColor = face.color.r !== 1 || face.color.g !== 1 || face.color.b !== 1;
        var hasFaceVertexColor = face.vertexColors.length > 0;
        var faceType = 0;
        faceType = setBit(faceType, 0, 0);
        faceType = setBit(faceType, 1, hasMaterial);
        faceType = setBit(faceType, 2, hasFaceUv);
        faceType = setBit(faceType, 3, hasFaceVertexUv);
        faceType = setBit(faceType, 4, hasFaceNormal);
        faceType = setBit(faceType, 5, hasFaceVertexNormal);
        faceType = setBit(faceType, 6, hasFaceColor);
        faceType = setBit(faceType, 7, hasFaceVertexColor);
        faces.push(faceType);
        faces.push(face.a, face.b, face.c);
        faces.push(face.materialIndex);
        if (hasFaceVertexUv) {
          var faceVertexUvs = this.faceVertexUvs[0][i];
          faces.push(getUvIndex(faceVertexUvs[0]), getUvIndex(faceVertexUvs[1]), getUvIndex(faceVertexUvs[2]));
        }
        if (hasFaceNormal) {
          faces.push(getNormalIndex(face.normal));
        }
        if (hasFaceVertexNormal) {
          var vertexNormals = face.vertexNormals;
          faces.push(getNormalIndex(vertexNormals[0]), getNormalIndex(vertexNormals[1]), getNormalIndex(vertexNormals[2]));
        }
        if (hasFaceColor) {
          faces.push(getColorIndex(face.color));
        }
        if (hasFaceVertexColor) {
          var vertexColors = face.vertexColors;
          faces.push(getColorIndex(vertexColors[0]), getColorIndex(vertexColors[1]), getColorIndex(vertexColors[2]));
        }
      }
      function setBit(value, position, enabled) {
        return enabled ? value | (1 << position) : value & (~(1 << position));
      }
      function getNormalIndex(normal) {
        var hash = normal.x.toString() + normal.y.toString() + normal.z.toString();
        if (normalsHash[hash] !== undefined) {
          return normalsHash[hash];
        }
        normalsHash[hash] = normals.length / 3;
        normals.push(normal.x, normal.y, normal.z);
        return normalsHash[hash];
      }
      function getColorIndex(color) {
        var hash = color.r.toString() + color.g.toString() + color.b.toString();
        if (colorsHash[hash] !== undefined) {
          return colorsHash[hash];
        }
        colorsHash[hash] = colors.length;
        colors.push(color.getHex());
        return colorsHash[hash];
      }
      function getUvIndex(uv) {
        var hash = uv.x.toString() + uv.y.toString();
        if (uvsHash[hash] !== undefined) {
          return uvsHash[hash];
        }
        uvsHash[hash] = uvs.length / 2;
        uvs.push(uv.x, uv.y);
        return uvsHash[hash];
      }
      data.data = {};
      data.data.vertices = vertices;
      data.data.normals = normals;
      if (colors.length > 0)
        data.data.colors = colors;
      if (uvs.length > 0)
        data.data.uvs = [uvs];
      data.data.faces = faces;
      return data;
    },
    clone: function() {
      return new THREE.Geometry().copy(this);
    },
    copy: function(source) {
      this.vertices = [];
      this.faces = [];
      this.faceVertexUvs = [[]];
      var vertices = source.vertices;
      for (var i = 0,
          il = vertices.length; i < il; i++) {
        this.vertices.push(vertices[i].clone());
      }
      var faces = source.faces;
      for (var i = 0,
          il = faces.length; i < il; i++) {
        this.faces.push(faces[i].clone());
      }
      for (var i = 0,
          il = source.faceVertexUvs.length; i < il; i++) {
        var faceVertexUvs = source.faceVertexUvs[i];
        if (this.faceVertexUvs[i] === undefined) {
          this.faceVertexUvs[i] = [];
        }
        for (var j = 0,
            jl = faceVertexUvs.length; j < jl; j++) {
          var uvs = faceVertexUvs[j],
              uvsCopy = [];
          for (var k = 0,
              kl = uvs.length; k < kl; k++) {
            var uv = uvs[k];
            uvsCopy.push(uv.clone());
          }
          this.faceVertexUvs[i].push(uvsCopy);
        }
      }
      return this;
    },
    dispose: function() {
      this.dispatchEvent({type: 'dispose'});
    }
  });
  THREE.GeometryIdCount = 0;
  THREE.DirectGeometry = function() {
    Object.defineProperty(this, 'id', {value: THREE.GeometryIdCount++});
    this.uuid = THREE.Math.generateUUID();
    this.name = '';
    this.type = 'DirectGeometry';
    this.indices = [];
    this.vertices = [];
    this.normals = [];
    this.colors = [];
    this.uvs = [];
    this.uvs2 = [];
    this.groups = [];
    this.morphTargets = {};
    this.skinWeights = [];
    this.skinIndices = [];
    this.boundingBox = null;
    this.boundingSphere = null;
    this.verticesNeedUpdate = false;
    this.normalsNeedUpdate = false;
    this.colorsNeedUpdate = false;
    this.uvsNeedUpdate = false;
    this.groupsNeedUpdate = false;
  };
  Object.assign(THREE.DirectGeometry.prototype, THREE.EventDispatcher.prototype, {
    computeBoundingBox: THREE.Geometry.prototype.computeBoundingBox,
    computeBoundingSphere: THREE.Geometry.prototype.computeBoundingSphere,
    computeFaceNormals: function() {
      console.warn('THREE.DirectGeometry: computeFaceNormals() is not a method of this type of geometry.');
    },
    computeVertexNormals: function() {
      console.warn('THREE.DirectGeometry: computeVertexNormals() is not a method of this type of geometry.');
    },
    computeGroups: function(geometry) {
      var group;
      var groups = [];
      var materialIndex;
      var faces = geometry.faces;
      for (var i = 0; i < faces.length; i++) {
        var face = faces[i];
        if (face.materialIndex !== materialIndex) {
          materialIndex = face.materialIndex;
          if (group !== undefined) {
            group.count = (i * 3) - group.start;
            groups.push(group);
          }
          group = {
            start: i * 3,
            materialIndex: materialIndex
          };
        }
      }
      if (group !== undefined) {
        group.count = (i * 3) - group.start;
        groups.push(group);
      }
      this.groups = groups;
    },
    fromGeometry: function(geometry) {
      var faces = geometry.faces;
      var vertices = geometry.vertices;
      var faceVertexUvs = geometry.faceVertexUvs;
      var hasFaceVertexUv = faceVertexUvs[0] && faceVertexUvs[0].length > 0;
      var hasFaceVertexUv2 = faceVertexUvs[1] && faceVertexUvs[1].length > 0;
      var morphTargets = geometry.morphTargets;
      var morphTargetsLength = morphTargets.length;
      var morphTargetsPosition;
      if (morphTargetsLength > 0) {
        morphTargetsPosition = [];
        for (var i = 0; i < morphTargetsLength; i++) {
          morphTargetsPosition[i] = [];
        }
        this.morphTargets.position = morphTargetsPosition;
      }
      var morphNormals = geometry.morphNormals;
      var morphNormalsLength = morphNormals.length;
      var morphTargetsNormal;
      if (morphNormalsLength > 0) {
        morphTargetsNormal = [];
        for (var i = 0; i < morphNormalsLength; i++) {
          morphTargetsNormal[i] = [];
        }
        this.morphTargets.normal = morphTargetsNormal;
      }
      var skinIndices = geometry.skinIndices;
      var skinWeights = geometry.skinWeights;
      var hasSkinIndices = skinIndices.length === vertices.length;
      var hasSkinWeights = skinWeights.length === vertices.length;
      for (var i = 0; i < faces.length; i++) {
        var face = faces[i];
        this.vertices.push(vertices[face.a], vertices[face.b], vertices[face.c]);
        var vertexNormals = face.vertexNormals;
        if (vertexNormals.length === 3) {
          this.normals.push(vertexNormals[0], vertexNormals[1], vertexNormals[2]);
        } else {
          var normal = face.normal;
          this.normals.push(normal, normal, normal);
        }
        var vertexColors = face.vertexColors;
        if (vertexColors.length === 3) {
          this.colors.push(vertexColors[0], vertexColors[1], vertexColors[2]);
        } else {
          var color = face.color;
          this.colors.push(color, color, color);
        }
        if (hasFaceVertexUv === true) {
          var vertexUvs = faceVertexUvs[0][i];
          if (vertexUvs !== undefined) {
            this.uvs.push(vertexUvs[0], vertexUvs[1], vertexUvs[2]);
          } else {
            console.warn('THREE.DirectGeometry.fromGeometry(): Undefined vertexUv ', i);
            this.uvs.push(new THREE.Vector2(), new THREE.Vector2(), new THREE.Vector2());
          }
        }
        if (hasFaceVertexUv2 === true) {
          var vertexUvs = faceVertexUvs[1][i];
          if (vertexUvs !== undefined) {
            this.uvs2.push(vertexUvs[0], vertexUvs[1], vertexUvs[2]);
          } else {
            console.warn('THREE.DirectGeometry.fromGeometry(): Undefined vertexUv2 ', i);
            this.uvs2.push(new THREE.Vector2(), new THREE.Vector2(), new THREE.Vector2());
          }
        }
        for (var j = 0; j < morphTargetsLength; j++) {
          var morphTarget = morphTargets[j].vertices;
          morphTargetsPosition[j].push(morphTarget[face.a], morphTarget[face.b], morphTarget[face.c]);
        }
        for (var j = 0; j < morphNormalsLength; j++) {
          var morphNormal = morphNormals[j].vertexNormals[i];
          morphTargetsNormal[j].push(morphNormal.a, morphNormal.b, morphNormal.c);
        }
        if (hasSkinIndices) {
          this.skinIndices.push(skinIndices[face.a], skinIndices[face.b], skinIndices[face.c]);
        }
        if (hasSkinWeights) {
          this.skinWeights.push(skinWeights[face.a], skinWeights[face.b], skinWeights[face.c]);
        }
      }
      this.computeGroups(geometry);
      this.verticesNeedUpdate = geometry.verticesNeedUpdate;
      this.normalsNeedUpdate = geometry.normalsNeedUpdate;
      this.colorsNeedUpdate = geometry.colorsNeedUpdate;
      this.uvsNeedUpdate = geometry.uvsNeedUpdate;
      this.groupsNeedUpdate = geometry.groupsNeedUpdate;
      return this;
    },
    dispose: function() {
      this.dispatchEvent({type: 'dispose'});
    }
  });
  THREE.BufferGeometry = function() {
    Object.defineProperty(this, 'id', {value: THREE.GeometryIdCount++});
    this.uuid = THREE.Math.generateUUID();
    this.name = '';
    this.type = 'BufferGeometry';
    this.index = null;
    this.attributes = {};
    this.morphAttributes = {};
    this.groups = [];
    this.boundingBox = null;
    this.boundingSphere = null;
    this.drawRange = {
      start: 0,
      count: Infinity
    };
  };
  Object.assign(THREE.BufferGeometry.prototype, THREE.EventDispatcher.prototype, {
    getIndex: function() {
      return this.index;
    },
    setIndex: function(index) {
      this.index = index;
    },
    addAttribute: function(name, attribute) {
      if (attribute instanceof THREE.BufferAttribute === false && attribute instanceof THREE.InterleavedBufferAttribute === false) {
        console.warn('THREE.BufferGeometry: .addAttribute() now expects ( name, attribute ).');
        this.addAttribute(name, new THREE.BufferAttribute(arguments[1], arguments[2]));
        return;
      }
      if (name === 'index') {
        console.warn('THREE.BufferGeometry.addAttribute: Use .setIndex() for index attribute.');
        this.setIndex(attribute);
        return;
      }
      this.attributes[name] = attribute;
      return this;
    },
    getAttribute: function(name) {
      return this.attributes[name];
    },
    removeAttribute: function(name) {
      delete this.attributes[name];
      return this;
    },
    addGroup: function(start, count, materialIndex) {
      this.groups.push({
        start: start,
        count: count,
        materialIndex: materialIndex !== undefined ? materialIndex : 0
      });
    },
    clearGroups: function() {
      this.groups = [];
    },
    setDrawRange: function(start, count) {
      this.drawRange.start = start;
      this.drawRange.count = count;
    },
    applyMatrix: function(matrix) {
      var position = this.attributes.position;
      if (position !== undefined) {
        matrix.applyToVector3Array(position.array);
        position.needsUpdate = true;
      }
      var normal = this.attributes.normal;
      if (normal !== undefined) {
        var normalMatrix = new THREE.Matrix3().getNormalMatrix(matrix);
        normalMatrix.applyToVector3Array(normal.array);
        normal.needsUpdate = true;
      }
      if (this.boundingBox !== null) {
        this.computeBoundingBox();
      }
      if (this.boundingSphere !== null) {
        this.computeBoundingSphere();
      }
      return this;
    },
    rotateX: function() {
      var m1;
      return function rotateX(angle) {
        if (m1 === undefined)
          m1 = new THREE.Matrix4();
        m1.makeRotationX(angle);
        this.applyMatrix(m1);
        return this;
      };
    }(),
    rotateY: function() {
      var m1;
      return function rotateY(angle) {
        if (m1 === undefined)
          m1 = new THREE.Matrix4();
        m1.makeRotationY(angle);
        this.applyMatrix(m1);
        return this;
      };
    }(),
    rotateZ: function() {
      var m1;
      return function rotateZ(angle) {
        if (m1 === undefined)
          m1 = new THREE.Matrix4();
        m1.makeRotationZ(angle);
        this.applyMatrix(m1);
        return this;
      };
    }(),
    translate: function() {
      var m1;
      return function translate(x, y, z) {
        if (m1 === undefined)
          m1 = new THREE.Matrix4();
        m1.makeTranslation(x, y, z);
        this.applyMatrix(m1);
        return this;
      };
    }(),
    scale: function() {
      var m1;
      return function scale(x, y, z) {
        if (m1 === undefined)
          m1 = new THREE.Matrix4();
        m1.makeScale(x, y, z);
        this.applyMatrix(m1);
        return this;
      };
    }(),
    lookAt: function() {
      var obj;
      return function lookAt(vector) {
        if (obj === undefined)
          obj = new THREE.Object3D();
        obj.lookAt(vector);
        obj.updateMatrix();
        this.applyMatrix(obj.matrix);
      };
    }(),
    center: function() {
      this.computeBoundingBox();
      var offset = this.boundingBox.center().negate();
      this.translate(offset.x, offset.y, offset.z);
      return offset;
    },
    setFromObject: function(object) {
      var geometry = object.geometry;
      if (object instanceof THREE.Points || object instanceof THREE.Line) {
        var positions = new THREE.Float32Attribute(geometry.vertices.length * 3, 3);
        var colors = new THREE.Float32Attribute(geometry.colors.length * 3, 3);
        this.addAttribute('position', positions.copyVector3sArray(geometry.vertices));
        this.addAttribute('color', colors.copyColorsArray(geometry.colors));
        if (geometry.lineDistances && geometry.lineDistances.length === geometry.vertices.length) {
          var lineDistances = new THREE.Float32Attribute(geometry.lineDistances.length, 1);
          this.addAttribute('lineDistance', lineDistances.copyArray(geometry.lineDistances));
        }
        if (geometry.boundingSphere !== null) {
          this.boundingSphere = geometry.boundingSphere.clone();
        }
        if (geometry.boundingBox !== null) {
          this.boundingBox = geometry.boundingBox.clone();
        }
      } else if (object instanceof THREE.Mesh) {
        if (geometry instanceof THREE.Geometry) {
          this.fromGeometry(geometry);
        }
      }
      return this;
    },
    updateFromObject: function(object) {
      var geometry = object.geometry;
      if (object instanceof THREE.Mesh) {
        var direct = geometry.__directGeometry;
        if (direct === undefined) {
          return this.fromGeometry(geometry);
        }
        direct.verticesNeedUpdate = geometry.verticesNeedUpdate;
        direct.normalsNeedUpdate = geometry.normalsNeedUpdate;
        direct.colorsNeedUpdate = geometry.colorsNeedUpdate;
        direct.uvsNeedUpdate = geometry.uvsNeedUpdate;
        direct.groupsNeedUpdate = geometry.groupsNeedUpdate;
        geometry.verticesNeedUpdate = false;
        geometry.normalsNeedUpdate = false;
        geometry.colorsNeedUpdate = false;
        geometry.uvsNeedUpdate = false;
        geometry.groupsNeedUpdate = false;
        geometry = direct;
      }
      if (geometry.verticesNeedUpdate === true) {
        var attribute = this.attributes.position;
        if (attribute !== undefined) {
          attribute.copyVector3sArray(geometry.vertices);
          attribute.needsUpdate = true;
        }
        geometry.verticesNeedUpdate = false;
      }
      if (geometry.normalsNeedUpdate === true) {
        var attribute = this.attributes.normal;
        if (attribute !== undefined) {
          attribute.copyVector3sArray(geometry.normals);
          attribute.needsUpdate = true;
        }
        geometry.normalsNeedUpdate = false;
      }
      if (geometry.colorsNeedUpdate === true) {
        var attribute = this.attributes.color;
        if (attribute !== undefined) {
          attribute.copyColorsArray(geometry.colors);
          attribute.needsUpdate = true;
        }
        geometry.colorsNeedUpdate = false;
      }
      if (geometry.uvsNeedUpdate) {
        var attribute = this.attributes.uv;
        if (attribute !== undefined) {
          attribute.copyVector2sArray(geometry.uvs);
          attribute.needsUpdate = true;
        }
        geometry.uvsNeedUpdate = false;
      }
      if (geometry.lineDistancesNeedUpdate) {
        var attribute = this.attributes.lineDistance;
        if (attribute !== undefined) {
          attribute.copyArray(geometry.lineDistances);
          attribute.needsUpdate = true;
        }
        geometry.lineDistancesNeedUpdate = false;
      }
      if (geometry.groupsNeedUpdate) {
        geometry.computeGroups(object.geometry);
        this.groups = geometry.groups;
        geometry.groupsNeedUpdate = false;
      }
      return this;
    },
    fromGeometry: function(geometry) {
      geometry.__directGeometry = new THREE.DirectGeometry().fromGeometry(geometry);
      return this.fromDirectGeometry(geometry.__directGeometry);
    },
    fromDirectGeometry: function(geometry) {
      var positions = new Float32Array(geometry.vertices.length * 3);
      this.addAttribute('position', new THREE.BufferAttribute(positions, 3).copyVector3sArray(geometry.vertices));
      if (geometry.normals.length > 0) {
        var normals = new Float32Array(geometry.normals.length * 3);
        this.addAttribute('normal', new THREE.BufferAttribute(normals, 3).copyVector3sArray(geometry.normals));
      }
      if (geometry.colors.length > 0) {
        var colors = new Float32Array(geometry.colors.length * 3);
        this.addAttribute('color', new THREE.BufferAttribute(colors, 3).copyColorsArray(geometry.colors));
      }
      if (geometry.uvs.length > 0) {
        var uvs = new Float32Array(geometry.uvs.length * 2);
        this.addAttribute('uv', new THREE.BufferAttribute(uvs, 2).copyVector2sArray(geometry.uvs));
      }
      if (geometry.uvs2.length > 0) {
        var uvs2 = new Float32Array(geometry.uvs2.length * 2);
        this.addAttribute('uv2', new THREE.BufferAttribute(uvs2, 2).copyVector2sArray(geometry.uvs2));
      }
      if (geometry.indices.length > 0) {
        var TypeArray = geometry.vertices.length > 65535 ? Uint32Array : Uint16Array;
        var indices = new TypeArray(geometry.indices.length * 3);
        this.setIndex(new THREE.BufferAttribute(indices, 1).copyIndicesArray(geometry.indices));
      }
      this.groups = geometry.groups;
      for (var name in geometry.morphTargets) {
        var array = [];
        var morphTargets = geometry.morphTargets[name];
        for (var i = 0,
            l = morphTargets.length; i < l; i++) {
          var morphTarget = morphTargets[i];
          var attribute = new THREE.Float32Attribute(morphTarget.length * 3, 3);
          array.push(attribute.copyVector3sArray(morphTarget));
        }
        this.morphAttributes[name] = array;
      }
      if (geometry.skinIndices.length > 0) {
        var skinIndices = new THREE.Float32Attribute(geometry.skinIndices.length * 4, 4);
        this.addAttribute('skinIndex', skinIndices.copyVector4sArray(geometry.skinIndices));
      }
      if (geometry.skinWeights.length > 0) {
        var skinWeights = new THREE.Float32Attribute(geometry.skinWeights.length * 4, 4);
        this.addAttribute('skinWeight', skinWeights.copyVector4sArray(geometry.skinWeights));
      }
      if (geometry.boundingSphere !== null) {
        this.boundingSphere = geometry.boundingSphere.clone();
      }
      if (geometry.boundingBox !== null) {
        this.boundingBox = geometry.boundingBox.clone();
      }
      return this;
    },
    computeBoundingBox: function() {
      if (this.boundingBox === null) {
        this.boundingBox = new THREE.Box3();
      }
      var positions = this.attributes.position.array;
      if (positions !== undefined) {
        this.boundingBox.setFromArray(positions);
      } else {
        this.boundingBox.makeEmpty();
      }
      if (isNaN(this.boundingBox.min.x) || isNaN(this.boundingBox.min.y) || isNaN(this.boundingBox.min.z)) {
        console.error('THREE.BufferGeometry.computeBoundingBox: Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this);
      }
    },
    computeBoundingSphere: function() {
      var box = new THREE.Box3();
      var vector = new THREE.Vector3();
      return function computeBoundingSphere() {
        if (this.boundingSphere === null) {
          this.boundingSphere = new THREE.Sphere();
        }
        var positions = this.attributes.position;
        if (positions) {
          var array = positions.array;
          var center = this.boundingSphere.center;
          box.setFromArray(array);
          box.center(center);
          var maxRadiusSq = 0;
          for (var i = 0,
              il = array.length; i < il; i += 3) {
            vector.fromArray(array, i);
            maxRadiusSq = Math.max(maxRadiusSq, center.distanceToSquared(vector));
          }
          this.boundingSphere.radius = Math.sqrt(maxRadiusSq);
          if (isNaN(this.boundingSphere.radius)) {
            console.error('THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this);
          }
        }
      };
    }(),
    computeFaceNormals: function() {},
    computeVertexNormals: function() {
      var index = this.index;
      var attributes = this.attributes;
      var groups = this.groups;
      if (attributes.position) {
        var positions = attributes.position.array;
        if (attributes.normal === undefined) {
          this.addAttribute('normal', new THREE.BufferAttribute(new Float32Array(positions.length), 3));
        } else {
          var array = attributes.normal.array;
          for (var i = 0,
              il = array.length; i < il; i++) {
            array[i] = 0;
          }
        }
        var normals = attributes.normal.array;
        var vA,
            vB,
            vC,
            pA = new THREE.Vector3(),
            pB = new THREE.Vector3(),
            pC = new THREE.Vector3(),
            cb = new THREE.Vector3(),
            ab = new THREE.Vector3();
        if (index) {
          var indices = index.array;
          if (groups.length === 0) {
            this.addGroup(0, indices.length);
          }
          for (var j = 0,
              jl = groups.length; j < jl; ++j) {
            var group = groups[j];
            var start = group.start;
            var count = group.count;
            for (var i = start,
                il = start + count; i < il; i += 3) {
              vA = indices[i + 0] * 3;
              vB = indices[i + 1] * 3;
              vC = indices[i + 2] * 3;
              pA.fromArray(positions, vA);
              pB.fromArray(positions, vB);
              pC.fromArray(positions, vC);
              cb.subVectors(pC, pB);
              ab.subVectors(pA, pB);
              cb.cross(ab);
              normals[vA] += cb.x;
              normals[vA + 1] += cb.y;
              normals[vA + 2] += cb.z;
              normals[vB] += cb.x;
              normals[vB + 1] += cb.y;
              normals[vB + 2] += cb.z;
              normals[vC] += cb.x;
              normals[vC + 1] += cb.y;
              normals[vC + 2] += cb.z;
            }
          }
        } else {
          for (var i = 0,
              il = positions.length; i < il; i += 9) {
            pA.fromArray(positions, i);
            pB.fromArray(positions, i + 3);
            pC.fromArray(positions, i + 6);
            cb.subVectors(pC, pB);
            ab.subVectors(pA, pB);
            cb.cross(ab);
            normals[i] = cb.x;
            normals[i + 1] = cb.y;
            normals[i + 2] = cb.z;
            normals[i + 3] = cb.x;
            normals[i + 4] = cb.y;
            normals[i + 5] = cb.z;
            normals[i + 6] = cb.x;
            normals[i + 7] = cb.y;
            normals[i + 8] = cb.z;
          }
        }
        this.normalizeNormals();
        attributes.normal.needsUpdate = true;
      }
    },
    merge: function(geometry, offset) {
      if (geometry instanceof THREE.BufferGeometry === false) {
        console.error('THREE.BufferGeometry.merge(): geometry not an instance of THREE.BufferGeometry.', geometry);
        return;
      }
      if (offset === undefined)
        offset = 0;
      var attributes = this.attributes;
      for (var key in attributes) {
        if (geometry.attributes[key] === undefined)
          continue;
        var attribute1 = attributes[key];
        var attributeArray1 = attribute1.array;
        var attribute2 = geometry.attributes[key];
        var attributeArray2 = attribute2.array;
        var attributeSize = attribute2.itemSize;
        for (var i = 0,
            j = attributeSize * offset; i < attributeArray2.length; i++, j++) {
          attributeArray1[j] = attributeArray2[i];
        }
      }
      return this;
    },
    normalizeNormals: function() {
      var normals = this.attributes.normal.array;
      var x,
          y,
          z,
          n;
      for (var i = 0,
          il = normals.length; i < il; i += 3) {
        x = normals[i];
        y = normals[i + 1];
        z = normals[i + 2];
        n = 1.0 / Math.sqrt(x * x + y * y + z * z);
        normals[i] *= n;
        normals[i + 1] *= n;
        normals[i + 2] *= n;
      }
    },
    toNonIndexed: function() {
      if (this.index === null) {
        console.warn('THREE.BufferGeometry.toNonIndexed(): Geometry is already non-indexed.');
        return this;
      }
      var geometry2 = new THREE.BufferGeometry();
      var indices = this.index.array;
      var attributes = this.attributes;
      for (var name in attributes) {
        var attribute = attributes[name];
        var array = attribute.array;
        var itemSize = attribute.itemSize;
        var array2 = new array.constructor(indices.length * itemSize);
        var index = 0,
            index2 = 0;
        for (var i = 0,
            l = indices.length; i < l; i++) {
          index = indices[i] * itemSize;
          for (var j = 0; j < itemSize; j++) {
            array2[index2++] = array[index++];
          }
        }
        geometry2.addAttribute(name, new THREE.BufferAttribute(array2, itemSize));
      }
      return geometry2;
    },
    toJSON: function() {
      var data = {metadata: {
          version: 4.4,
          type: 'BufferGeometry',
          generator: 'BufferGeometry.toJSON'
        }};
      data.uuid = this.uuid;
      data.type = this.type;
      if (this.name !== '')
        data.name = this.name;
      if (this.parameters !== undefined) {
        var parameters = this.parameters;
        for (var key in parameters) {
          if (parameters[key] !== undefined)
            data[key] = parameters[key];
        }
        return data;
      }
      data.data = {attributes: {}};
      var index = this.index;
      if (index !== null) {
        var array = Array.prototype.slice.call(index.array);
        data.data.index = {
          type: index.array.constructor.name,
          array: array
        };
      }
      var attributes = this.attributes;
      for (var key in attributes) {
        var attribute = attributes[key];
        var array = Array.prototype.slice.call(attribute.array);
        data.data.attributes[key] = {
          itemSize: attribute.itemSize,
          type: attribute.array.constructor.name,
          array: array,
          normalized: attribute.normalized
        };
      }
      var groups = this.groups;
      if (groups.length > 0) {
        data.data.groups = JSON.parse(JSON.stringify(groups));
      }
      var boundingSphere = this.boundingSphere;
      if (boundingSphere !== null) {
        data.data.boundingSphere = {
          center: boundingSphere.center.toArray(),
          radius: boundingSphere.radius
        };
      }
      return data;
    },
    clone: function() {
      return new THREE.BufferGeometry().copy(this);
    },
    copy: function(source) {
      var index = source.index;
      if (index !== null) {
        this.setIndex(index.clone());
      }
      var attributes = source.attributes;
      for (var name in attributes) {
        var attribute = attributes[name];
        this.addAttribute(name, attribute.clone());
      }
      var groups = source.groups;
      for (var i = 0,
          l = groups.length; i < l; i++) {
        var group = groups[i];
        this.addGroup(group.start, group.count, group.materialIndex);
      }
      return this;
    },
    dispose: function() {
      this.dispatchEvent({type: 'dispose'});
    }
  });
  THREE.BufferGeometry.MaxIndex = 65535;
  THREE.InstancedBufferGeometry = function() {
    THREE.BufferGeometry.call(this);
    this.type = 'InstancedBufferGeometry';
    this.maxInstancedCount = undefined;
  };
  THREE.InstancedBufferGeometry.prototype = Object.create(THREE.BufferGeometry.prototype);
  THREE.InstancedBufferGeometry.prototype.constructor = THREE.InstancedBufferGeometry;
  THREE.InstancedBufferGeometry.prototype.addGroup = function(start, count, instances) {
    this.groups.push({
      start: start,
      count: count,
      instances: instances
    });
  };
  THREE.InstancedBufferGeometry.prototype.copy = function(source) {
    var index = source.index;
    if (index !== null) {
      this.setIndex(index.clone());
    }
    var attributes = source.attributes;
    for (var name in attributes) {
      var attribute = attributes[name];
      this.addAttribute(name, attribute.clone());
    }
    var groups = source.groups;
    for (var i = 0,
        l = groups.length; i < l; i++) {
      var group = groups[i];
      this.addGroup(group.start, group.count, group.instances);
    }
    return this;
  };
  THREE.Uniform = function(value) {
    if (typeof value === 'string') {
      console.warn('THREE.Uniform: Type parameter is no longer needed.');
      value = arguments[1];
    }
    this.value = value;
    this.dynamic = false;
  };
  THREE.Uniform.prototype = {
    constructor: THREE.Uniform,
    onUpdate: function(callback) {
      this.dynamic = true;
      this.onUpdateCallback = callback;
      return this;
    }
  };
  THREE.AnimationAction = function() {
    throw new Error("THREE.AnimationAction: " + "Use mixer.clipAction for construction.");
  };
  THREE.AnimationAction._new = function AnimationAction(mixer, clip, localRoot) {
    this._mixer = mixer;
    this._clip = clip;
    this._localRoot = localRoot || null;
    var tracks = clip.tracks,
        nTracks = tracks.length,
        interpolants = new Array(nTracks);
    var interpolantSettings = {
      endingStart: THREE.ZeroCurvatureEnding,
      endingEnd: THREE.ZeroCurvatureEnding
    };
    for (var i = 0; i !== nTracks; ++i) {
      var interpolant = tracks[i].createInterpolant(null);
      interpolants[i] = interpolant;
      interpolant.settings = interpolantSettings;
    }
    this._interpolantSettings = interpolantSettings;
    this._interpolants = interpolants;
    this._propertyBindings = new Array(nTracks);
    this._cacheIndex = null;
    this._byClipCacheIndex = null;
    this._timeScaleInterpolant = null;
    this._weightInterpolant = null;
    this.loop = THREE.LoopRepeat;
    this._loopCount = -1;
    this._startTime = null;
    this.time = 0;
    this.timeScale = 1;
    this._effectiveTimeScale = 1;
    this.weight = 1;
    this._effectiveWeight = 1;
    this.repetitions = Infinity;
    this.paused = false;
    this.enabled = true;
    this.clampWhenFinished = false;
    this.zeroSlopeAtStart = true;
    this.zeroSlopeAtEnd = true;
  };
  THREE.AnimationAction._new.prototype = {
    constructor: THREE.AnimationAction._new,
    play: function() {
      this._mixer._activateAction(this);
      return this;
    },
    stop: function() {
      this._mixer._deactivateAction(this);
      return this.reset();
    },
    reset: function() {
      this.paused = false;
      this.enabled = true;
      this.time = 0;
      this._loopCount = -1;
      this._startTime = null;
      return this.stopFading().stopWarping();
    },
    isRunning: function() {
      var start = this._startTime;
      return this.enabled && !this.paused && this.timeScale !== 0 && this._startTime === null && this._mixer._isActiveAction(this);
    },
    isScheduled: function() {
      return this._mixer._isActiveAction(this);
    },
    startAt: function(time) {
      this._startTime = time;
      return this;
    },
    setLoop: function(mode, repetitions) {
      this.loop = mode;
      this.repetitions = repetitions;
      return this;
    },
    setEffectiveWeight: function(weight) {
      this.weight = weight;
      this._effectiveWeight = this.enabled ? weight : 0;
      return this.stopFading();
    },
    getEffectiveWeight: function() {
      return this._effectiveWeight;
    },
    fadeIn: function(duration) {
      return this._scheduleFading(duration, 0, 1);
    },
    fadeOut: function(duration) {
      return this._scheduleFading(duration, 1, 0);
    },
    crossFadeFrom: function(fadeOutAction, duration, warp) {
      var mixer = this._mixer;
      fadeOutAction.fadeOut(duration);
      this.fadeIn(duration);
      if (warp) {
        var fadeInDuration = this._clip.duration,
            fadeOutDuration = fadeOutAction._clip.duration,
            startEndRatio = fadeOutDuration / fadeInDuration,
            endStartRatio = fadeInDuration / fadeOutDuration;
        fadeOutAction.warp(1.0, startEndRatio, duration);
        this.warp(endStartRatio, 1.0, duration);
      }
      return this;
    },
    crossFadeTo: function(fadeInAction, duration, warp) {
      return fadeInAction.crossFadeFrom(this, duration, warp);
    },
    stopFading: function() {
      var weightInterpolant = this._weightInterpolant;
      if (weightInterpolant !== null) {
        this._weightInterpolant = null;
        this._mixer._takeBackControlInterpolant(weightInterpolant);
      }
      return this;
    },
    setEffectiveTimeScale: function(timeScale) {
      this.timeScale = timeScale;
      this._effectiveTimeScale = this.paused ? 0 : timeScale;
      return this.stopWarping();
    },
    getEffectiveTimeScale: function() {
      return this._effectiveTimeScale;
    },
    setDuration: function(duration) {
      this.timeScale = this._clip.duration / duration;
      return this.stopWarping();
    },
    syncWith: function(action) {
      this.time = action.time;
      this.timeScale = action.timeScale;
      return this.stopWarping();
    },
    halt: function(duration) {
      return this.warp(this._effectiveTimeScale, 0, duration);
    },
    warp: function(startTimeScale, endTimeScale, duration) {
      var mixer = this._mixer,
          now = mixer.time,
          interpolant = this._timeScaleInterpolant,
          timeScale = this.timeScale;
      if (interpolant === null) {
        interpolant = mixer._lendControlInterpolant(), this._timeScaleInterpolant = interpolant;
      }
      var times = interpolant.parameterPositions,
          values = interpolant.sampleValues;
      times[0] = now;
      times[1] = now + duration;
      values[0] = startTimeScale / timeScale;
      values[1] = endTimeScale / timeScale;
      return this;
    },
    stopWarping: function() {
      var timeScaleInterpolant = this._timeScaleInterpolant;
      if (timeScaleInterpolant !== null) {
        this._timeScaleInterpolant = null;
        this._mixer._takeBackControlInterpolant(timeScaleInterpolant);
      }
      return this;
    },
    getMixer: function() {
      return this._mixer;
    },
    getClip: function() {
      return this._clip;
    },
    getRoot: function() {
      return this._localRoot || this._mixer._root;
    },
    _update: function(time, deltaTime, timeDirection, accuIndex) {
      var startTime = this._startTime;
      if (startTime !== null) {
        var timeRunning = (time - startTime) * timeDirection;
        if (timeRunning < 0 || timeDirection === 0) {
          return;
        }
        this._startTime = null;
        deltaTime = timeDirection * timeRunning;
      }
      deltaTime *= this._updateTimeScale(time);
      var clipTime = this._updateTime(deltaTime);
      var weight = this._updateWeight(time);
      if (weight > 0) {
        var interpolants = this._interpolants;
        var propertyMixers = this._propertyBindings;
        for (var j = 0,
            m = interpolants.length; j !== m; ++j) {
          interpolants[j].evaluate(clipTime);
          propertyMixers[j].accumulate(accuIndex, weight);
        }
      }
    },
    _updateWeight: function(time) {
      var weight = 0;
      if (this.enabled) {
        weight = this.weight;
        var interpolant = this._weightInterpolant;
        if (interpolant !== null) {
          var interpolantValue = interpolant.evaluate(time)[0];
          weight *= interpolantValue;
          if (time > interpolant.parameterPositions[1]) {
            this.stopFading();
            if (interpolantValue === 0) {
              this.enabled = false;
            }
          }
        }
      }
      this._effectiveWeight = weight;
      return weight;
    },
    _updateTimeScale: function(time) {
      var timeScale = 0;
      if (!this.paused) {
        timeScale = this.timeScale;
        var interpolant = this._timeScaleInterpolant;
        if (interpolant !== null) {
          var interpolantValue = interpolant.evaluate(time)[0];
          timeScale *= interpolantValue;
          if (time > interpolant.parameterPositions[1]) {
            this.stopWarping();
            if (timeScale === 0) {
              this.paused = true;
            } else {
              this.timeScale = timeScale;
            }
          }
        }
      }
      this._effectiveTimeScale = timeScale;
      return timeScale;
    },
    _updateTime: function(deltaTime) {
      var time = this.time + deltaTime;
      if (deltaTime === 0)
        return time;
      var duration = this._clip.duration,
          loop = this.loop,
          loopCount = this._loopCount;
      if (loop === THREE.LoopOnce) {
        if (loopCount === -1) {
          this.loopCount = 0;
          this._setEndings(true, true, false);
        }
        handle_stop: {
          if (time >= duration) {
            time = duration;
          } else if (time < 0) {
            time = 0;
          } else
            break handle_stop;
          if (this.clampWhenFinished)
            this.paused = true;
          else
            this.enabled = false;
          this._mixer.dispatchEvent({
            type: 'finished',
            action: this,
            direction: deltaTime < 0 ? -1 : 1
          });
        }
      } else {
        var pingPong = (loop === THREE.LoopPingPong);
        if (loopCount === -1) {
          if (deltaTime >= 0) {
            loopCount = 0;
            this._setEndings(true, this.repetitions === 0, pingPong);
          } else {
            this._setEndings(this.repetitions === 0, true, pingPong);
          }
        }
        if (time >= duration || time < 0) {
          var loopDelta = Math.floor(time / duration);
          time -= duration * loopDelta;
          loopCount += Math.abs(loopDelta);
          var pending = this.repetitions - loopCount;
          if (pending < 0) {
            if (this.clampWhenFinished)
              this.paused = true;
            else
              this.enabled = false;
            time = deltaTime > 0 ? duration : 0;
            this._mixer.dispatchEvent({
              type: 'finished',
              action: this,
              direction: deltaTime > 0 ? 1 : -1
            });
          } else {
            if (pending === 0) {
              var atStart = deltaTime < 0;
              this._setEndings(atStart, !atStart, pingPong);
            } else {
              this._setEndings(false, false, pingPong);
            }
            this._loopCount = loopCount;
            this._mixer.dispatchEvent({
              type: 'loop',
              action: this,
              loopDelta: loopDelta
            });
          }
        }
        if (pingPong && (loopCount & 1) === 1) {
          this.time = time;
          return duration - time;
        }
      }
      this.time = time;
      return time;
    },
    _setEndings: function(atStart, atEnd, pingPong) {
      var settings = this._interpolantSettings;
      if (pingPong) {
        settings.endingStart = THREE.ZeroSlopeEnding;
        settings.endingEnd = THREE.ZeroSlopeEnding;
      } else {
        if (atStart) {
          settings.endingStart = this.zeroSlopeAtStart ? THREE.ZeroSlopeEnding : THREE.ZeroCurvatureEnding;
        } else {
          settings.endingStart = THREE.WrapAroundEnding;
        }
        if (atEnd) {
          settings.endingEnd = this.zeroSlopeAtEnd ? THREE.ZeroSlopeEnding : THREE.ZeroCurvatureEnding;
        } else {
          settings.endingEnd = THREE.WrapAroundEnding;
        }
      }
    },
    _scheduleFading: function(duration, weightNow, weightThen) {
      var mixer = this._mixer,
          now = mixer.time,
          interpolant = this._weightInterpolant;
      if (interpolant === null) {
        interpolant = mixer._lendControlInterpolant(), this._weightInterpolant = interpolant;
      }
      var times = interpolant.parameterPositions,
          values = interpolant.sampleValues;
      times[0] = now;
      values[0] = weightNow;
      times[1] = now + duration;
      values[1] = weightThen;
      return this;
    }
  };
  THREE.AnimationClip = function(name, duration, tracks) {
    this.name = name;
    this.tracks = tracks;
    this.duration = (duration !== undefined) ? duration : -1;
    this.uuid = THREE.Math.generateUUID();
    if (this.duration < 0) {
      this.resetDuration();
    }
    this.trim();
    this.optimize();
  };
  THREE.AnimationClip.prototype = {
    constructor: THREE.AnimationClip,
    resetDuration: function() {
      var tracks = this.tracks,
          duration = 0;
      for (var i = 0,
          n = tracks.length; i !== n; ++i) {
        var track = this.tracks[i];
        duration = Math.max(duration, track.times[track.times.length - 1]);
      }
      this.duration = duration;
    },
    trim: function() {
      for (var i = 0; i < this.tracks.length; i++) {
        this.tracks[i].trim(0, this.duration);
      }
      return this;
    },
    optimize: function() {
      for (var i = 0; i < this.tracks.length; i++) {
        this.tracks[i].optimize();
      }
      return this;
    }
  };
  Object.assign(THREE.AnimationClip, {
    parse: function(json) {
      var tracks = [],
          jsonTracks = json.tracks,
          frameTime = 1.0 / (json.fps || 1.0);
      for (var i = 0,
          n = jsonTracks.length; i !== n; ++i) {
        tracks.push(THREE.KeyframeTrack.parse(jsonTracks[i]).scale(frameTime));
      }
      return new THREE.AnimationClip(json.name, json.duration, tracks);
    },
    toJSON: function(clip) {
      var tracks = [],
          clipTracks = clip.tracks;
      var json = {
        'name': clip.name,
        'duration': clip.duration,
        'tracks': tracks
      };
      for (var i = 0,
          n = clipTracks.length; i !== n; ++i) {
        tracks.push(THREE.KeyframeTrack.toJSON(clipTracks[i]));
      }
      return json;
    },
    CreateFromMorphTargetSequence: function(name, morphTargetSequence, fps, noLoop) {
      var numMorphTargets = morphTargetSequence.length;
      var tracks = [];
      for (var i = 0; i < numMorphTargets; i++) {
        var times = [];
        var values = [];
        times.push((i + numMorphTargets - 1) % numMorphTargets, i, (i + 1) % numMorphTargets);
        values.push(0, 1, 0);
        var order = THREE.AnimationUtils.getKeyframeOrder(times);
        times = THREE.AnimationUtils.sortedArray(times, 1, order);
        values = THREE.AnimationUtils.sortedArray(values, 1, order);
        if (!noLoop && times[0] === 0) {
          times.push(numMorphTargets);
          values.push(values[0]);
        }
        tracks.push(new THREE.NumberKeyframeTrack('.morphTargetInfluences[' + morphTargetSequence[i].name + ']', times, values).scale(1.0 / fps));
      }
      return new THREE.AnimationClip(name, -1, tracks);
    },
    findByName: function(objectOrClipArray, name) {
      var clipArray = objectOrClipArray;
      if (!Array.isArray(objectOrClipArray)) {
        var o = objectOrClipArray;
        clipArray = o.geometry && o.geometry.animations || o.animations;
      }
      for (var i = 0; i < clipArray.length; i++) {
        if (clipArray[i].name === name) {
          return clipArray[i];
        }
      }
      return null;
    },
    CreateClipsFromMorphTargetSequences: function(morphTargets, fps, noLoop) {
      var animationToMorphTargets = {};
      var pattern = /^([\w-]*?)([\d]+)$/;
      for (var i = 0,
          il = morphTargets.length; i < il; i++) {
        var morphTarget = morphTargets[i];
        var parts = morphTarget.name.match(pattern);
        if (parts && parts.length > 1) {
          var name = parts[1];
          var animationMorphTargets = animationToMorphTargets[name];
          if (!animationMorphTargets) {
            animationToMorphTargets[name] = animationMorphTargets = [];
          }
          animationMorphTargets.push(morphTarget);
        }
      }
      var clips = [];
      for (var name in animationToMorphTargets) {
        clips.push(THREE.AnimationClip.CreateFromMorphTargetSequence(name, animationToMorphTargets[name], fps, noLoop));
      }
      return clips;
    },
    parseAnimation: function(animation, bones, nodeName) {
      if (!animation) {
        console.error("  no animation in JSONLoader data");
        return null;
      }
      var addNonemptyTrack = function(trackType, trackName, animationKeys, propertyName, destTracks) {
        if (animationKeys.length !== 0) {
          var times = [];
          var values = [];
          THREE.AnimationUtils.flattenJSON(animationKeys, times, values, propertyName);
          if (times.length !== 0) {
            destTracks.push(new trackType(trackName, times, values));
          }
        }
      };
      var tracks = [];
      var clipName = animation.name || 'default';
      var duration = animation.length || -1;
      var fps = animation.fps || 30;
      var hierarchyTracks = animation.hierarchy || [];
      for (var h = 0; h < hierarchyTracks.length; h++) {
        var animationKeys = hierarchyTracks[h].keys;
        if (!animationKeys || animationKeys.length === 0)
          continue;
        if (animationKeys[0].morphTargets) {
          var morphTargetNames = {};
          for (var k = 0; k < animationKeys.length; k++) {
            if (animationKeys[k].morphTargets) {
              for (var m = 0; m < animationKeys[k].morphTargets.length; m++) {
                morphTargetNames[animationKeys[k].morphTargets[m]] = -1;
              }
            }
          }
          for (var morphTargetName in morphTargetNames) {
            var times = [];
            var values = [];
            for (var m = 0; m !== animationKeys[k].morphTargets.length; ++m) {
              var animationKey = animationKeys[k];
              times.push(animationKey.time);
              values.push((animationKey.morphTarget === morphTargetName) ? 1 : 0);
            }
            tracks.push(new THREE.NumberKeyframeTrack('.morphTargetInfluence[' + morphTargetName + ']', times, values));
          }
          duration = morphTargetNames.length * (fps || 1.0);
        } else {
          var boneName = '.bones[' + bones[h].name + ']';
          addNonemptyTrack(THREE.VectorKeyframeTrack, boneName + '.position', animationKeys, 'pos', tracks);
          addNonemptyTrack(THREE.QuaternionKeyframeTrack, boneName + '.quaternion', animationKeys, 'rot', tracks);
          addNonemptyTrack(THREE.VectorKeyframeTrack, boneName + '.scale', animationKeys, 'scl', tracks);
        }
      }
      if (tracks.length === 0) {
        return null;
      }
      var clip = new THREE.AnimationClip(clipName, duration, tracks);
      return clip;
    }
  });
  THREE.AnimationMixer = function(root) {
    this._root = root;
    this._initMemoryManager();
    this._accuIndex = 0;
    this.time = 0;
    this.timeScale = 1.0;
  };
  Object.assign(THREE.AnimationMixer.prototype, THREE.EventDispatcher.prototype, {
    clipAction: function(clip, optionalRoot) {
      var root = optionalRoot || this._root,
          rootUuid = root.uuid,
          clipObject = typeof clip === 'string' ? THREE.AnimationClip.findByName(root, clip) : clip,
          clipUuid = clipObject !== null ? clipObject.uuid : clip,
          actionsForClip = this._actionsByClip[clipUuid],
          prototypeAction = null;
      if (actionsForClip !== undefined) {
        var existingAction = actionsForClip.actionByRoot[rootUuid];
        if (existingAction !== undefined) {
          return existingAction;
        }
        prototypeAction = actionsForClip.knownActions[0];
        if (clipObject === null)
          clipObject = prototypeAction._clip;
      }
      if (clipObject === null)
        return null;
      var newAction = new THREE.AnimationMixer._Action(this, clipObject, optionalRoot);
      this._bindAction(newAction, prototypeAction);
      this._addInactiveAction(newAction, clipUuid, rootUuid);
      return newAction;
    },
    existingAction: function(clip, optionalRoot) {
      var root = optionalRoot || this._root,
          rootUuid = root.uuid,
          clipObject = typeof clip === 'string' ? THREE.AnimationClip.findByName(root, clip) : clip,
          clipUuid = clipObject ? clipObject.uuid : clip,
          actionsForClip = this._actionsByClip[clipUuid];
      if (actionsForClip !== undefined) {
        return actionsForClip.actionByRoot[rootUuid] || null;
      }
      return null;
    },
    stopAllAction: function() {
      var actions = this._actions,
          nActions = this._nActiveActions,
          bindings = this._bindings,
          nBindings = this._nActiveBindings;
      this._nActiveActions = 0;
      this._nActiveBindings = 0;
      for (var i = 0; i !== nActions; ++i) {
        actions[i].reset();
      }
      for (var i = 0; i !== nBindings; ++i) {
        bindings[i].useCount = 0;
      }
      return this;
    },
    update: function(deltaTime) {
      deltaTime *= this.timeScale;
      var actions = this._actions,
          nActions = this._nActiveActions,
          time = this.time += deltaTime,
          timeDirection = Math.sign(deltaTime),
          accuIndex = this._accuIndex ^= 1;
      for (var i = 0; i !== nActions; ++i) {
        var action = actions[i];
        if (action.enabled) {
          action._update(time, deltaTime, timeDirection, accuIndex);
        }
      }
      var bindings = this._bindings,
          nBindings = this._nActiveBindings;
      for (var i = 0; i !== nBindings; ++i) {
        bindings[i].apply(accuIndex);
      }
      return this;
    },
    getRoot: function() {
      return this._root;
    },
    uncacheClip: function(clip) {
      var actions = this._actions,
          clipUuid = clip.uuid,
          actionsByClip = this._actionsByClip,
          actionsForClip = actionsByClip[clipUuid];
      if (actionsForClip !== undefined) {
        var actionsToRemove = actionsForClip.knownActions;
        for (var i = 0,
            n = actionsToRemove.length; i !== n; ++i) {
          var action = actionsToRemove[i];
          this._deactivateAction(action);
          var cacheIndex = action._cacheIndex,
              lastInactiveAction = actions[actions.length - 1];
          action._cacheIndex = null;
          action._byClipCacheIndex = null;
          lastInactiveAction._cacheIndex = cacheIndex;
          actions[cacheIndex] = lastInactiveAction;
          actions.pop();
          this._removeInactiveBindingsForAction(action);
        }
        delete actionsByClip[clipUuid];
      }
    },
    uncacheRoot: function(root) {
      var rootUuid = root.uuid,
          actionsByClip = this._actionsByClip;
      for (var clipUuid in actionsByClip) {
        var actionByRoot = actionsByClip[clipUuid].actionByRoot,
            action = actionByRoot[rootUuid];
        if (action !== undefined) {
          this._deactivateAction(action);
          this._removeInactiveAction(action);
        }
      }
      var bindingsByRoot = this._bindingsByRootAndName,
          bindingByName = bindingsByRoot[rootUuid];
      if (bindingByName !== undefined) {
        for (var trackName in bindingByName) {
          var binding = bindingByName[trackName];
          binding.restoreOriginalState();
          this._removeInactiveBinding(binding);
        }
      }
    },
    uncacheAction: function(clip, optionalRoot) {
      var action = this.existingAction(clip, optionalRoot);
      if (action !== null) {
        this._deactivateAction(action);
        this._removeInactiveAction(action);
      }
    }
  });
  THREE.AnimationMixer._Action = THREE.AnimationAction._new;
  Object.assign(THREE.AnimationMixer.prototype, {
    _bindAction: function(action, prototypeAction) {
      var root = action._localRoot || this._root,
          tracks = action._clip.tracks,
          nTracks = tracks.length,
          bindings = action._propertyBindings,
          interpolants = action._interpolants,
          rootUuid = root.uuid,
          bindingsByRoot = this._bindingsByRootAndName,
          bindingsByName = bindingsByRoot[rootUuid];
      if (bindingsByName === undefined) {
        bindingsByName = {};
        bindingsByRoot[rootUuid] = bindingsByName;
      }
      for (var i = 0; i !== nTracks; ++i) {
        var track = tracks[i],
            trackName = track.name,
            binding = bindingsByName[trackName];
        if (binding !== undefined) {
          bindings[i] = binding;
        } else {
          binding = bindings[i];
          if (binding !== undefined) {
            if (binding._cacheIndex === null) {
              ++binding.referenceCount;
              this._addInactiveBinding(binding, rootUuid, trackName);
            }
            continue;
          }
          var path = prototypeAction && prototypeAction._propertyBindings[i].binding.parsedPath;
          binding = new THREE.PropertyMixer(THREE.PropertyBinding.create(root, trackName, path), track.ValueTypeName, track.getValueSize());
          ++binding.referenceCount;
          this._addInactiveBinding(binding, rootUuid, trackName);
          bindings[i] = binding;
        }
        interpolants[i].resultBuffer = binding.buffer;
      }
    },
    _activateAction: function(action) {
      if (!this._isActiveAction(action)) {
        if (action._cacheIndex === null) {
          var rootUuid = (action._localRoot || this._root).uuid,
              clipUuid = action._clip.uuid,
              actionsForClip = this._actionsByClip[clipUuid];
          this._bindAction(action, actionsForClip && actionsForClip.knownActions[0]);
          this._addInactiveAction(action, clipUuid, rootUuid);
        }
        var bindings = action._propertyBindings;
        for (var i = 0,
            n = bindings.length; i !== n; ++i) {
          var binding = bindings[i];
          if (binding.useCount++ === 0) {
            this._lendBinding(binding);
            binding.saveOriginalState();
          }
        }
        this._lendAction(action);
      }
    },
    _deactivateAction: function(action) {
      if (this._isActiveAction(action)) {
        var bindings = action._propertyBindings;
        for (var i = 0,
            n = bindings.length; i !== n; ++i) {
          var binding = bindings[i];
          if (--binding.useCount === 0) {
            binding.restoreOriginalState();
            this._takeBackBinding(binding);
          }
        }
        this._takeBackAction(action);
      }
    },
    _initMemoryManager: function() {
      this._actions = [];
      this._nActiveActions = 0;
      this._actionsByClip = {};
      this._bindings = [];
      this._nActiveBindings = 0;
      this._bindingsByRootAndName = {};
      this._controlInterpolants = [];
      this._nActiveControlInterpolants = 0;
      var scope = this;
      this.stats = {
        actions: {
          get total() {
            return scope._actions.length;
          },
          get inUse() {
            return scope._nActiveActions;
          }
        },
        bindings: {
          get total() {
            return scope._bindings.length;
          },
          get inUse() {
            return scope._nActiveBindings;
          }
        },
        controlInterpolants: {
          get total() {
            return scope._controlInterpolants.length;
          },
          get inUse() {
            return scope._nActiveControlInterpolants;
          }
        }
      };
    },
    _isActiveAction: function(action) {
      var index = action._cacheIndex;
      return index !== null && index < this._nActiveActions;
    },
    _addInactiveAction: function(action, clipUuid, rootUuid) {
      var actions = this._actions,
          actionsByClip = this._actionsByClip,
          actionsForClip = actionsByClip[clipUuid];
      if (actionsForClip === undefined) {
        actionsForClip = {
          knownActions: [action],
          actionByRoot: {}
        };
        action._byClipCacheIndex = 0;
        actionsByClip[clipUuid] = actionsForClip;
      } else {
        var knownActions = actionsForClip.knownActions;
        action._byClipCacheIndex = knownActions.length;
        knownActions.push(action);
      }
      action._cacheIndex = actions.length;
      actions.push(action);
      actionsForClip.actionByRoot[rootUuid] = action;
    },
    _removeInactiveAction: function(action) {
      var actions = this._actions,
          lastInactiveAction = actions[actions.length - 1],
          cacheIndex = action._cacheIndex;
      lastInactiveAction._cacheIndex = cacheIndex;
      actions[cacheIndex] = lastInactiveAction;
      actions.pop();
      action._cacheIndex = null;
      var clipUuid = action._clip.uuid,
          actionsByClip = this._actionsByClip,
          actionsForClip = actionsByClip[clipUuid],
          knownActionsForClip = actionsForClip.knownActions,
          lastKnownAction = knownActionsForClip[knownActionsForClip.length - 1],
          byClipCacheIndex = action._byClipCacheIndex;
      lastKnownAction._byClipCacheIndex = byClipCacheIndex;
      knownActionsForClip[byClipCacheIndex] = lastKnownAction;
      knownActionsForClip.pop();
      action._byClipCacheIndex = null;
      var actionByRoot = actionsForClip.actionByRoot,
          rootUuid = (actions._localRoot || this._root).uuid;
      delete actionByRoot[rootUuid];
      if (knownActionsForClip.length === 0) {
        delete actionsByClip[clipUuid];
      }
      this._removeInactiveBindingsForAction(action);
    },
    _removeInactiveBindingsForAction: function(action) {
      var bindings = action._propertyBindings;
      for (var i = 0,
          n = bindings.length; i !== n; ++i) {
        var binding = bindings[i];
        if (--binding.referenceCount === 0) {
          this._removeInactiveBinding(binding);
        }
      }
    },
    _lendAction: function(action) {
      var actions = this._actions,
          prevIndex = action._cacheIndex,
          lastActiveIndex = this._nActiveActions++,
          firstInactiveAction = actions[lastActiveIndex];
      action._cacheIndex = lastActiveIndex;
      actions[lastActiveIndex] = action;
      firstInactiveAction._cacheIndex = prevIndex;
      actions[prevIndex] = firstInactiveAction;
    },
    _takeBackAction: function(action) {
      var actions = this._actions,
          prevIndex = action._cacheIndex,
          firstInactiveIndex = --this._nActiveActions,
          lastActiveAction = actions[firstInactiveIndex];
      action._cacheIndex = firstInactiveIndex;
      actions[firstInactiveIndex] = action;
      lastActiveAction._cacheIndex = prevIndex;
      actions[prevIndex] = lastActiveAction;
    },
    _addInactiveBinding: function(binding, rootUuid, trackName) {
      var bindingsByRoot = this._bindingsByRootAndName,
          bindingByName = bindingsByRoot[rootUuid],
          bindings = this._bindings;
      if (bindingByName === undefined) {
        bindingByName = {};
        bindingsByRoot[rootUuid] = bindingByName;
      }
      bindingByName[trackName] = binding;
      binding._cacheIndex = bindings.length;
      bindings.push(binding);
    },
    _removeInactiveBinding: function(binding) {
      var bindings = this._bindings,
          propBinding = binding.binding,
          rootUuid = propBinding.rootNode.uuid,
          trackName = propBinding.path,
          bindingsByRoot = this._bindingsByRootAndName,
          bindingByName = bindingsByRoot[rootUuid],
          lastInactiveBinding = bindings[bindings.length - 1],
          cacheIndex = binding._cacheIndex;
      lastInactiveBinding._cacheIndex = cacheIndex;
      bindings[cacheIndex] = lastInactiveBinding;
      bindings.pop();
      delete bindingByName[trackName];
      remove_empty_map: {
        for (var _ in bindingByName)
          break remove_empty_map;
        delete bindingsByRoot[rootUuid];
      }
    },
    _lendBinding: function(binding) {
      var bindings = this._bindings,
          prevIndex = binding._cacheIndex,
          lastActiveIndex = this._nActiveBindings++,
          firstInactiveBinding = bindings[lastActiveIndex];
      binding._cacheIndex = lastActiveIndex;
      bindings[lastActiveIndex] = binding;
      firstInactiveBinding._cacheIndex = prevIndex;
      bindings[prevIndex] = firstInactiveBinding;
    },
    _takeBackBinding: function(binding) {
      var bindings = this._bindings,
          prevIndex = binding._cacheIndex,
          firstInactiveIndex = --this._nActiveBindings,
          lastActiveBinding = bindings[firstInactiveIndex];
      binding._cacheIndex = firstInactiveIndex;
      bindings[firstInactiveIndex] = binding;
      lastActiveBinding._cacheIndex = prevIndex;
      bindings[prevIndex] = lastActiveBinding;
    },
    _lendControlInterpolant: function() {
      var interpolants = this._controlInterpolants,
          lastActiveIndex = this._nActiveControlInterpolants++,
          interpolant = interpolants[lastActiveIndex];
      if (interpolant === undefined) {
        interpolant = new THREE.LinearInterpolant(new Float32Array(2), new Float32Array(2), 1, this._controlInterpolantsResultBuffer);
        interpolant.__cacheIndex = lastActiveIndex;
        interpolants[lastActiveIndex] = interpolant;
      }
      return interpolant;
    },
    _takeBackControlInterpolant: function(interpolant) {
      var interpolants = this._controlInterpolants,
          prevIndex = interpolant.__cacheIndex,
          firstInactiveIndex = --this._nActiveControlInterpolants,
          lastActiveInterpolant = interpolants[firstInactiveIndex];
      interpolant.__cacheIndex = firstInactiveIndex;
      interpolants[firstInactiveIndex] = interpolant;
      lastActiveInterpolant.__cacheIndex = prevIndex;
      interpolants[prevIndex] = lastActiveInterpolant;
    },
    _controlInterpolantsResultBuffer: new Float32Array(1)
  });
  THREE.AnimationObjectGroup = function(var_args) {
    this.uuid = THREE.Math.generateUUID();
    this._objects = Array.prototype.slice.call(arguments);
    this.nCachedObjects_ = 0;
    var indices = {};
    this._indicesByUUID = indices;
    for (var i = 0,
        n = arguments.length; i !== n; ++i) {
      indices[arguments[i].uuid] = i;
    }
    this._paths = [];
    this._parsedPaths = [];
    this._bindings = [];
    this._bindingsIndicesByPath = {};
    var scope = this;
    this.stats = {
      objects: {
        get total() {
          return scope._objects.length;
        },
        get inUse() {
          return this.total - scope.nCachedObjects_;
        }
      },
      get bindingsPerObject() {
        return scope._bindings.length;
      }
    };
  };
  THREE.AnimationObjectGroup.prototype = {
    constructor: THREE.AnimationObjectGroup,
    add: function(var_args) {
      var objects = this._objects,
          nObjects = objects.length,
          nCachedObjects = this.nCachedObjects_,
          indicesByUUID = this._indicesByUUID,
          paths = this._paths,
          parsedPaths = this._parsedPaths,
          bindings = this._bindings,
          nBindings = bindings.length;
      for (var i = 0,
          n = arguments.length; i !== n; ++i) {
        var object = arguments[i],
            uuid = object.uuid,
            index = indicesByUUID[uuid];
        if (index === undefined) {
          index = nObjects++;
          indicesByUUID[uuid] = index;
          objects.push(object);
          for (var j = 0,
              m = nBindings; j !== m; ++j) {
            bindings[j].push(new THREE.PropertyBinding(object, paths[j], parsedPaths[j]));
          }
        } else if (index < nCachedObjects) {
          var knownObject = objects[index];
          var firstActiveIndex = --nCachedObjects,
              lastCachedObject = objects[firstActiveIndex];
          indicesByUUID[lastCachedObject.uuid] = index;
          objects[index] = lastCachedObject;
          indicesByUUID[uuid] = firstActiveIndex;
          objects[firstActiveIndex] = object;
          for (var j = 0,
              m = nBindings; j !== m; ++j) {
            var bindingsForPath = bindings[j],
                lastCached = bindingsForPath[firstActiveIndex],
                binding = bindingsForPath[index];
            bindingsForPath[index] = lastCached;
            if (binding === undefined) {
              binding = new THREE.PropertyBinding(object, paths[j], parsedPaths[j]);
            }
            bindingsForPath[firstActiveIndex] = binding;
          }
        } else if (objects[index] !== knownObject) {
          console.error("Different objects with the same UUID " + "detected. Clean the caches or recreate your " + "infrastructure when reloading scenes...");
        }
      }
      this.nCachedObjects_ = nCachedObjects;
    },
    remove: function(var_args) {
      var objects = this._objects,
          nObjects = objects.length,
          nCachedObjects = this.nCachedObjects_,
          indicesByUUID = this._indicesByUUID,
          bindings = this._bindings,
          nBindings = bindings.length;
      for (var i = 0,
          n = arguments.length; i !== n; ++i) {
        var object = arguments[i],
            uuid = object.uuid,
            index = indicesByUUID[uuid];
        if (index !== undefined && index >= nCachedObjects) {
          var lastCachedIndex = nCachedObjects++,
              firstActiveObject = objects[lastCachedIndex];
          indicesByUUID[firstActiveObject.uuid] = index;
          objects[index] = firstActiveObject;
          indicesByUUID[uuid] = lastCachedIndex;
          objects[lastCachedIndex] = object;
          for (var j = 0,
              m = nBindings; j !== m; ++j) {
            var bindingsForPath = bindings[j],
                firstActive = bindingsForPath[lastCachedIndex],
                binding = bindingsForPath[index];
            bindingsForPath[index] = firstActive;
            bindingsForPath[lastCachedIndex] = binding;
          }
        }
      }
      this.nCachedObjects_ = nCachedObjects;
    },
    uncache: function(var_args) {
      var objects = this._objects,
          nObjects = objects.length,
          nCachedObjects = this.nCachedObjects_,
          indicesByUUID = this._indicesByUUID,
          bindings = this._bindings,
          nBindings = bindings.length;
      for (var i = 0,
          n = arguments.length; i !== n; ++i) {
        var object = arguments[i],
            uuid = object.uuid,
            index = indicesByUUID[uuid];
        if (index !== undefined) {
          delete indicesByUUID[uuid];
          if (index < nCachedObjects) {
            var firstActiveIndex = --nCachedObjects,
                lastCachedObject = objects[firstActiveIndex],
                lastIndex = --nObjects,
                lastObject = objects[lastIndex];
            indicesByUUID[lastCachedObject.uuid] = index;
            objects[index] = lastCachedObject;
            indicesByUUID[lastObject.uuid] = firstActiveIndex;
            objects[firstActiveIndex] = lastObject;
            objects.pop();
            for (var j = 0,
                m = nBindings; j !== m; ++j) {
              var bindingsForPath = bindings[j],
                  lastCached = bindingsForPath[firstActiveIndex],
                  last = bindingsForPath[lastIndex];
              bindingsForPath[index] = lastCached;
              bindingsForPath[firstActiveIndex] = last;
              bindingsForPath.pop();
            }
          } else {
            var lastIndex = --nObjects,
                lastObject = objects[lastIndex];
            indicesByUUID[lastObject.uuid] = index;
            objects[index] = lastObject;
            objects.pop();
            for (var j = 0,
                m = nBindings; j !== m; ++j) {
              var bindingsForPath = bindings[j];
              bindingsForPath[index] = bindingsForPath[lastIndex];
              bindingsForPath.pop();
            }
          }
        }
      }
      this.nCachedObjects_ = nCachedObjects;
    },
    subscribe_: function(path, parsedPath) {
      var indicesByPath = this._bindingsIndicesByPath,
          index = indicesByPath[path],
          bindings = this._bindings;
      if (index !== undefined)
        return bindings[index];
      var paths = this._paths,
          parsedPaths = this._parsedPaths,
          objects = this._objects,
          nObjects = objects.length,
          nCachedObjects = this.nCachedObjects_,
          bindingsForPath = new Array(nObjects);
      index = bindings.length;
      indicesByPath[path] = index;
      paths.push(path);
      parsedPaths.push(parsedPath);
      bindings.push(bindingsForPath);
      for (var i = nCachedObjects,
          n = objects.length; i !== n; ++i) {
        var object = objects[i];
        bindingsForPath[i] = new THREE.PropertyBinding(object, path, parsedPath);
      }
      return bindingsForPath;
    },
    unsubscribe_: function(path) {
      var indicesByPath = this._bindingsIndicesByPath,
          index = indicesByPath[path];
      if (index !== undefined) {
        var paths = this._paths,
            parsedPaths = this._parsedPaths,
            bindings = this._bindings,
            lastBindingsIndex = bindings.length - 1,
            lastBindings = bindings[lastBindingsIndex],
            lastBindingsPath = path[lastBindingsIndex];
        indicesByPath[lastBindingsPath] = index;
        bindings[index] = lastBindings;
        bindings.pop();
        parsedPaths[index] = parsedPaths[lastBindingsIndex];
        parsedPaths.pop();
        paths[index] = paths[lastBindingsIndex];
        paths.pop();
      }
    }
  };
  THREE.AnimationUtils = {
    arraySlice: function(array, from, to) {
      if (THREE.AnimationUtils.isTypedArray(array)) {
        return new array.constructor(array.subarray(from, to));
      }
      return array.slice(from, to);
    },
    convertArray: function(array, type, forceClone) {
      if (!array || !forceClone && array.constructor === type)
        return array;
      if (typeof type.BYTES_PER_ELEMENT === 'number') {
        return new type(array);
      }
      return Array.prototype.slice.call(array);
    },
    isTypedArray: function(object) {
      return ArrayBuffer.isView(object) && !(object instanceof DataView);
    },
    getKeyframeOrder: function(times) {
      function compareTime(i, j) {
        return times[i] - times[j];
      }
      var n = times.length;
      var result = new Array(n);
      for (var i = 0; i !== n; ++i)
        result[i] = i;
      result.sort(compareTime);
      return result;
    },
    sortedArray: function(values, stride, order) {
      var nValues = values.length;
      var result = new values.constructor(nValues);
      for (var i = 0,
          dstOffset = 0; dstOffset !== nValues; ++i) {
        var srcOffset = order[i] * stride;
        for (var j = 0; j !== stride; ++j) {
          result[dstOffset++] = values[srcOffset + j];
        }
      }
      return result;
    },
    flattenJSON: function(jsonKeys, times, values, valuePropertyName) {
      var i = 1,
          key = jsonKeys[0];
      while (key !== undefined && key[valuePropertyName] === undefined) {
        key = jsonKeys[i++];
      }
      if (key === undefined)
        return;
      var value = key[valuePropertyName];
      if (value === undefined)
        return;
      if (Array.isArray(value)) {
        do {
          value = key[valuePropertyName];
          if (value !== undefined) {
            times.push(key.time);
            values.push.apply(values, value);
          }
          key = jsonKeys[i++];
        } while (key !== undefined);
      } else if (value.toArray !== undefined) {
        do {
          value = key[valuePropertyName];
          if (value !== undefined) {
            times.push(key.time);
            value.toArray(values, values.length);
          }
          key = jsonKeys[i++];
        } while (key !== undefined);
      } else {
        do {
          value = key[valuePropertyName];
          if (value !== undefined) {
            times.push(key.time);
            values.push(value);
          }
          key = jsonKeys[i++];
        } while (key !== undefined);
      }
    }
  };
  THREE.KeyframeTrack = function(name, times, values, interpolation) {
    if (name === undefined)
      throw new Error("track name is undefined");
    if (times === undefined || times.length === 0) {
      throw new Error("no keyframes in track named " + name);
    }
    this.name = name;
    this.times = THREE.AnimationUtils.convertArray(times, this.TimeBufferType);
    this.values = THREE.AnimationUtils.convertArray(values, this.ValueBufferType);
    this.setInterpolation(interpolation || this.DefaultInterpolation);
    this.validate();
    this.optimize();
  };
  THREE.KeyframeTrack.prototype = {
    constructor: THREE.KeyframeTrack,
    TimeBufferType: Float32Array,
    ValueBufferType: Float32Array,
    DefaultInterpolation: THREE.InterpolateLinear,
    InterpolantFactoryMethodDiscrete: function(result) {
      return new THREE.DiscreteInterpolant(this.times, this.values, this.getValueSize(), result);
    },
    InterpolantFactoryMethodLinear: function(result) {
      return new THREE.LinearInterpolant(this.times, this.values, this.getValueSize(), result);
    },
    InterpolantFactoryMethodSmooth: function(result) {
      return new THREE.CubicInterpolant(this.times, this.values, this.getValueSize(), result);
    },
    setInterpolation: function(interpolation) {
      var factoryMethod;
      switch (interpolation) {
        case THREE.InterpolateDiscrete:
          factoryMethod = this.InterpolantFactoryMethodDiscrete;
          break;
        case THREE.InterpolateLinear:
          factoryMethod = this.InterpolantFactoryMethodLinear;
          break;
        case THREE.InterpolateSmooth:
          factoryMethod = this.InterpolantFactoryMethodSmooth;
          break;
      }
      if (factoryMethod === undefined) {
        var message = "unsupported interpolation for " + this.ValueTypeName + " keyframe track named " + this.name;
        if (this.createInterpolant === undefined) {
          if (interpolation !== this.DefaultInterpolation) {
            this.setInterpolation(this.DefaultInterpolation);
          } else {
            throw new Error(message);
          }
        }
        console.warn(message);
        return;
      }
      this.createInterpolant = factoryMethod;
    },
    getInterpolation: function() {
      switch (this.createInterpolant) {
        case this.InterpolantFactoryMethodDiscrete:
          return THREE.InterpolateDiscrete;
        case this.InterpolantFactoryMethodLinear:
          return THREE.InterpolateLinear;
        case this.InterpolantFactoryMethodSmooth:
          return THREE.InterpolateSmooth;
      }
    },
    getValueSize: function() {
      return this.values.length / this.times.length;
    },
    shift: function(timeOffset) {
      if (timeOffset !== 0.0) {
        var times = this.times;
        for (var i = 0,
            n = times.length; i !== n; ++i) {
          times[i] += timeOffset;
        }
      }
      return this;
    },
    scale: function(timeScale) {
      if (timeScale !== 1.0) {
        var times = this.times;
        for (var i = 0,
            n = times.length; i !== n; ++i) {
          times[i] *= timeScale;
        }
      }
      return this;
    },
    trim: function(startTime, endTime) {
      var times = this.times,
          nKeys = times.length,
          from = 0,
          to = nKeys - 1;
      while (from !== nKeys && times[from] < startTime)
        ++from;
      while (to !== -1 && times[to] > endTime)
        --to;
      ++to;
      if (from !== 0 || to !== nKeys) {
        if (from >= to)
          to = Math.max(to, 1), from = to - 1;
        var stride = this.getValueSize();
        this.times = THREE.AnimationUtils.arraySlice(times, from, to);
        this.values = THREE.AnimationUtils.arraySlice(this.values, from * stride, to * stride);
      }
      return this;
    },
    validate: function() {
      var valid = true;
      var valueSize = this.getValueSize();
      if (valueSize - Math.floor(valueSize) !== 0) {
        console.error("invalid value size in track", this);
        valid = false;
      }
      var times = this.times,
          values = this.values,
          nKeys = times.length;
      if (nKeys === 0) {
        console.error("track is empty", this);
        valid = false;
      }
      var prevTime = null;
      for (var i = 0; i !== nKeys; i++) {
        var currTime = times[i];
        if (typeof currTime === 'number' && isNaN(currTime)) {
          console.error("time is not a valid number", this, i, currTime);
          valid = false;
          break;
        }
        if (prevTime !== null && prevTime > currTime) {
          console.error("out of order keys", this, i, currTime, prevTime);
          valid = false;
          break;
        }
        prevTime = currTime;
      }
      if (values !== undefined) {
        if (THREE.AnimationUtils.isTypedArray(values)) {
          for (var i = 0,
              n = values.length; i !== n; ++i) {
            var value = values[i];
            if (isNaN(value)) {
              console.error("value is not a valid number", this, i, value);
              valid = false;
              break;
            }
          }
        }
      }
      return valid;
    },
    optimize: function() {
      var times = this.times,
          values = this.values,
          stride = this.getValueSize(),
          writeIndex = 1;
      for (var i = 1,
          n = times.length - 1; i <= n; ++i) {
        var keep = false;
        var time = times[i];
        var timeNext = times[i + 1];
        if (time !== timeNext && (i !== 1 || time !== time[0])) {
          var offset = i * stride,
              offsetP = offset - stride,
              offsetN = offset + stride;
          for (var j = 0; j !== stride; ++j) {
            var value = values[offset + j];
            if (value !== values[offsetP + j] || value !== values[offsetN + j]) {
              keep = true;
              break;
            }
          }
        }
        if (keep) {
          if (i !== writeIndex) {
            times[writeIndex] = times[i];
            var readOffset = i * stride,
                writeOffset = writeIndex * stride;
            for (var j = 0; j !== stride; ++j) {
              values[writeOffset + j] = values[readOffset + j];
            }
          }
          ++writeIndex;
        }
      }
      if (writeIndex !== times.length) {
        this.times = THREE.AnimationUtils.arraySlice(times, 0, writeIndex);
        this.values = THREE.AnimationUtils.arraySlice(values, 0, writeIndex * stride);
      }
      return this;
    }
  };
  Object.assign(THREE.KeyframeTrack, {
    parse: function(json) {
      if (json.type === undefined) {
        throw new Error("track type undefined, can not parse");
      }
      var trackType = THREE.KeyframeTrack._getTrackTypeForValueTypeName(json.type);
      if (json.times === undefined) {
        var times = [],
            values = [];
        THREE.AnimationUtils.flattenJSON(json.keys, times, values, 'value');
        json.times = times;
        json.values = values;
      }
      if (trackType.parse !== undefined) {
        return trackType.parse(json);
      } else {
        return new trackType(json.name, json.times, json.values, json.interpolation);
      }
    },
    toJSON: function(track) {
      var trackType = track.constructor;
      var json;
      if (trackType.toJSON !== undefined) {
        json = trackType.toJSON(track);
      } else {
        json = {
          'name': track.name,
          'times': THREE.AnimationUtils.convertArray(track.times, Array),
          'values': THREE.AnimationUtils.convertArray(track.values, Array)
        };
        var interpolation = track.getInterpolation();
        if (interpolation !== track.DefaultInterpolation) {
          json.interpolation = interpolation;
        }
      }
      json.type = track.ValueTypeName;
      return json;
    },
    _getTrackTypeForValueTypeName: function(typeName) {
      switch (typeName.toLowerCase()) {
        case "scalar":
        case "double":
        case "float":
        case "number":
        case "integer":
          return THREE.NumberKeyframeTrack;
        case "vector":
        case "vector2":
        case "vector3":
        case "vector4":
          return THREE.VectorKeyframeTrack;
        case "color":
          return THREE.ColorKeyframeTrack;
        case "quaternion":
          return THREE.QuaternionKeyframeTrack;
        case "bool":
        case "boolean":
          return THREE.BooleanKeyframeTrack;
        case "string":
          return THREE.StringKeyframeTrack;
      }
      throw new Error("Unsupported typeName: " + typeName);
    }
  });
  THREE.PropertyBinding = function(rootNode, path, parsedPath) {
    this.path = path;
    this.parsedPath = parsedPath || THREE.PropertyBinding.parseTrackName(path);
    this.node = THREE.PropertyBinding.findNode(rootNode, this.parsedPath.nodeName) || rootNode;
    this.rootNode = rootNode;
  };
  THREE.PropertyBinding.prototype = {
    constructor: THREE.PropertyBinding,
    getValue: function getValue_unbound(targetArray, offset) {
      this.bind();
      this.getValue(targetArray, offset);
    },
    setValue: function getValue_unbound(sourceArray, offset) {
      this.bind();
      this.setValue(sourceArray, offset);
    },
    bind: function() {
      var targetObject = this.node,
          parsedPath = this.parsedPath,
          objectName = parsedPath.objectName,
          propertyName = parsedPath.propertyName,
          propertyIndex = parsedPath.propertyIndex;
      if (!targetObject) {
        targetObject = THREE.PropertyBinding.findNode(this.rootNode, parsedPath.nodeName) || this.rootNode;
        this.node = targetObject;
      }
      this.getValue = this._getValue_unavailable;
      this.setValue = this._setValue_unavailable;
      if (!targetObject) {
        console.error("  trying to update node for track: " + this.path + " but it wasn't found.");
        return;
      }
      if (objectName) {
        var objectIndex = parsedPath.objectIndex;
        switch (objectName) {
          case 'materials':
            if (!targetObject.material) {
              console.error('  can not bind to material as node does not have a material', this);
              return;
            }
            if (!targetObject.material.materials) {
              console.error('  can not bind to material.materials as node.material does not have a materials array', this);
              return;
            }
            targetObject = targetObject.material.materials;
            break;
          case 'bones':
            if (!targetObject.skeleton) {
              console.error('  can not bind to bones as node does not have a skeleton', this);
              return;
            }
            targetObject = targetObject.skeleton.bones;
            for (var i = 0; i < targetObject.length; i++) {
              if (targetObject[i].name === objectIndex) {
                objectIndex = i;
                break;
              }
            }
            break;
          default:
            if (targetObject[objectName] === undefined) {
              console.error('  can not bind to objectName of node, undefined', this);
              return;
            }
            targetObject = targetObject[objectName];
        }
        if (objectIndex !== undefined) {
          if (targetObject[objectIndex] === undefined) {
            console.error("  trying to bind to objectIndex of objectName, but is undefined:", this, targetObject);
            return;
          }
          targetObject = targetObject[objectIndex];
        }
      }
      var nodeProperty = targetObject[propertyName];
      if (nodeProperty === undefined) {
        var nodeName = parsedPath.nodeName;
        console.error("  trying to update property for track: " + nodeName + '.' + propertyName + " but it wasn't found.", targetObject);
        return;
      }
      var versioning = this.Versioning.None;
      if (targetObject.needsUpdate !== undefined) {
        versioning = this.Versioning.NeedsUpdate;
        this.targetObject = targetObject;
      } else if (targetObject.matrixWorldNeedsUpdate !== undefined) {
        versioning = this.Versioning.MatrixWorldNeedsUpdate;
        this.targetObject = targetObject;
      }
      var bindingType = this.BindingType.Direct;
      if (propertyIndex !== undefined) {
        if (propertyName === "morphTargetInfluences") {
          if (!targetObject.geometry) {
            console.error('  can not bind to morphTargetInfluences becasuse node does not have a geometry', this);
            return;
          }
          if (!targetObject.geometry.morphTargets) {
            console.error('  can not bind to morphTargetInfluences becasuse node does not have a geometry.morphTargets', this);
            return;
          }
          for (var i = 0; i < this.node.geometry.morphTargets.length; i++) {
            if (targetObject.geometry.morphTargets[i].name === propertyIndex) {
              propertyIndex = i;
              break;
            }
          }
        }
        bindingType = this.BindingType.ArrayElement;
        this.resolvedProperty = nodeProperty;
        this.propertyIndex = propertyIndex;
      } else if (nodeProperty.fromArray !== undefined && nodeProperty.toArray !== undefined) {
        bindingType = this.BindingType.HasFromToArray;
        this.resolvedProperty = nodeProperty;
      } else if (nodeProperty.length !== undefined) {
        bindingType = this.BindingType.EntireArray;
        this.resolvedProperty = nodeProperty;
      } else {
        this.propertyName = propertyName;
      }
      this.getValue = this.GetterByBindingType[bindingType];
      this.setValue = this.SetterByBindingTypeAndVersioning[bindingType][versioning];
    },
    unbind: function() {
      this.node = null;
      this.getValue = this._getValue_unbound;
      this.setValue = this._setValue_unbound;
    }
  };
  Object.assign(THREE.PropertyBinding.prototype, {
    _getValue_unavailable: function() {},
    _setValue_unavailable: function() {},
    _getValue_unbound: THREE.PropertyBinding.prototype.getValue,
    _setValue_unbound: THREE.PropertyBinding.prototype.setValue,
    BindingType: {
      Direct: 0,
      EntireArray: 1,
      ArrayElement: 2,
      HasFromToArray: 3
    },
    Versioning: {
      None: 0,
      NeedsUpdate: 1,
      MatrixWorldNeedsUpdate: 2
    },
    GetterByBindingType: [function getValue_direct(buffer, offset) {
      buffer[offset] = this.node[this.propertyName];
    }, function getValue_array(buffer, offset) {
      var source = this.resolvedProperty;
      for (var i = 0,
          n = source.length; i !== n; ++i) {
        buffer[offset++] = source[i];
      }
    }, function getValue_arrayElement(buffer, offset) {
      buffer[offset] = this.resolvedProperty[this.propertyIndex];
    }, function getValue_toArray(buffer, offset) {
      this.resolvedProperty.toArray(buffer, offset);
    }],
    SetterByBindingTypeAndVersioning: [[function setValue_direct(buffer, offset) {
      this.node[this.propertyName] = buffer[offset];
    }, function setValue_direct_setNeedsUpdate(buffer, offset) {
      this.node[this.propertyName] = buffer[offset];
      this.targetObject.needsUpdate = true;
    }, function setValue_direct_setMatrixWorldNeedsUpdate(buffer, offset) {
      this.node[this.propertyName] = buffer[offset];
      this.targetObject.matrixWorldNeedsUpdate = true;
    }], [function setValue_array(buffer, offset) {
      var dest = this.resolvedProperty;
      for (var i = 0,
          n = dest.length; i !== n; ++i) {
        dest[i] = buffer[offset++];
      }
    }, function setValue_array_setNeedsUpdate(buffer, offset) {
      var dest = this.resolvedProperty;
      for (var i = 0,
          n = dest.length; i !== n; ++i) {
        dest[i] = buffer[offset++];
      }
      this.targetObject.needsUpdate = true;
    }, function setValue_array_setMatrixWorldNeedsUpdate(buffer, offset) {
      var dest = this.resolvedProperty;
      for (var i = 0,
          n = dest.length; i !== n; ++i) {
        dest[i] = buffer[offset++];
      }
      this.targetObject.matrixWorldNeedsUpdate = true;
    }], [function setValue_arrayElement(buffer, offset) {
      this.resolvedProperty[this.propertyIndex] = buffer[offset];
    }, function setValue_arrayElement_setNeedsUpdate(buffer, offset) {
      this.resolvedProperty[this.propertyIndex] = buffer[offset];
      this.targetObject.needsUpdate = true;
    }, function setValue_arrayElement_setMatrixWorldNeedsUpdate(buffer, offset) {
      this.resolvedProperty[this.propertyIndex] = buffer[offset];
      this.targetObject.matrixWorldNeedsUpdate = true;
    }], [function setValue_fromArray(buffer, offset) {
      this.resolvedProperty.fromArray(buffer, offset);
    }, function setValue_fromArray_setNeedsUpdate(buffer, offset) {
      this.resolvedProperty.fromArray(buffer, offset);
      this.targetObject.needsUpdate = true;
    }, function setValue_fromArray_setMatrixWorldNeedsUpdate(buffer, offset) {
      this.resolvedProperty.fromArray(buffer, offset);
      this.targetObject.matrixWorldNeedsUpdate = true;
    }]]
  });
  THREE.PropertyBinding.Composite = function(targetGroup, path, optionalParsedPath) {
    var parsedPath = optionalParsedPath || THREE.PropertyBinding.parseTrackName(path);
    this._targetGroup = targetGroup;
    this._bindings = targetGroup.subscribe_(path, parsedPath);
  };
  THREE.PropertyBinding.Composite.prototype = {
    constructor: THREE.PropertyBinding.Composite,
    getValue: function(array, offset) {
      this.bind();
      var firstValidIndex = this._targetGroup.nCachedObjects_,
          binding = this._bindings[firstValidIndex];
      if (binding !== undefined)
        binding.getValue(array, offset);
    },
    setValue: function(array, offset) {
      var bindings = this._bindings;
      for (var i = this._targetGroup.nCachedObjects_,
          n = bindings.length; i !== n; ++i) {
        bindings[i].setValue(array, offset);
      }
    },
    bind: function() {
      var bindings = this._bindings;
      for (var i = this._targetGroup.nCachedObjects_,
          n = bindings.length; i !== n; ++i) {
        bindings[i].bind();
      }
    },
    unbind: function() {
      var bindings = this._bindings;
      for (var i = this._targetGroup.nCachedObjects_,
          n = bindings.length; i !== n; ++i) {
        bindings[i].unbind();
      }
    }
  };
  THREE.PropertyBinding.create = function(root, path, parsedPath) {
    if (!(root instanceof THREE.AnimationObjectGroup)) {
      return new THREE.PropertyBinding(root, path, parsedPath);
    } else {
      return new THREE.PropertyBinding.Composite(root, path, parsedPath);
    }
  };
  THREE.PropertyBinding.parseTrackName = function(trackName) {
    var re = /^(([\w]+\/)*)([\w-\d]+)?(\.([\w]+)(\[([\w\d\[\]\_.:\- ]+)\])?)?(\.([\w.]+)(\[([\w\d\[\]\_. ]+)\])?)$/;
    var matches = re.exec(trackName);
    if (!matches) {
      throw new Error("cannot parse trackName at all: " + trackName);
    }
    if (matches.index === re.lastIndex) {
      re.lastIndex++;
    }
    var results = {
      nodeName: matches[3],
      objectName: matches[5],
      objectIndex: matches[7],
      propertyName: matches[9],
      propertyIndex: matches[11]
    };
    if (results.propertyName === null || results.propertyName.length === 0) {
      throw new Error("can not parse propertyName from trackName: " + trackName);
    }
    return results;
  };
  THREE.PropertyBinding.findNode = function(root, nodeName) {
    if (!nodeName || nodeName === "" || nodeName === "root" || nodeName === "." || nodeName === -1 || nodeName === root.name || nodeName === root.uuid) {
      return root;
    }
    if (root.skeleton) {
      var searchSkeleton = function(skeleton) {
        for (var i = 0; i < skeleton.bones.length; i++) {
          var bone = skeleton.bones[i];
          if (bone.name === nodeName) {
            return bone;
          }
        }
        return null;
      };
      var bone = searchSkeleton(root.skeleton);
      if (bone) {
        return bone;
      }
    }
    if (root.children) {
      var searchNodeSubtree = function(children) {
        for (var i = 0; i < children.length; i++) {
          var childNode = children[i];
          if (childNode.name === nodeName || childNode.uuid === nodeName) {
            return childNode;
          }
          var result = searchNodeSubtree(childNode.children);
          if (result)
            return result;
        }
        return null;
      };
      var subTreeNode = searchNodeSubtree(root.children);
      if (subTreeNode) {
        return subTreeNode;
      }
    }
    return null;
  };
  THREE.PropertyMixer = function(binding, typeName, valueSize) {
    this.binding = binding;
    this.valueSize = valueSize;
    var bufferType = Float64Array,
        mixFunction;
    switch (typeName) {
      case 'quaternion':
        mixFunction = this._slerp;
        break;
      case 'string':
      case 'bool':
        bufferType = Array, mixFunction = this._select;
        break;
      default:
        mixFunction = this._lerp;
    }
    this.buffer = new bufferType(valueSize * 4);
    this._mixBufferRegion = mixFunction;
    this.cumulativeWeight = 0;
    this.useCount = 0;
    this.referenceCount = 0;
  };
  THREE.PropertyMixer.prototype = {
    constructor: THREE.PropertyMixer,
    accumulate: function(accuIndex, weight) {
      var buffer = this.buffer,
          stride = this.valueSize,
          offset = accuIndex * stride + stride,
          currentWeight = this.cumulativeWeight;
      if (currentWeight === 0) {
        for (var i = 0; i !== stride; ++i) {
          buffer[offset + i] = buffer[i];
        }
        currentWeight = weight;
      } else {
        currentWeight += weight;
        var mix = weight / currentWeight;
        this._mixBufferRegion(buffer, offset, 0, mix, stride);
      }
      this.cumulativeWeight = currentWeight;
    },
    apply: function(accuIndex) {
      var stride = this.valueSize,
          buffer = this.buffer,
          offset = accuIndex * stride + stride,
          weight = this.cumulativeWeight,
          binding = this.binding;
      this.cumulativeWeight = 0;
      if (weight < 1) {
        var originalValueOffset = stride * 3;
        this._mixBufferRegion(buffer, offset, originalValueOffset, 1 - weight, stride);
      }
      for (var i = stride,
          e = stride + stride; i !== e; ++i) {
        if (buffer[i] !== buffer[i + stride]) {
          binding.setValue(buffer, offset);
          break;
        }
      }
    },
    saveOriginalState: function() {
      var binding = this.binding;
      var buffer = this.buffer,
          stride = this.valueSize,
          originalValueOffset = stride * 3;
      binding.getValue(buffer, originalValueOffset);
      for (var i = stride,
          e = originalValueOffset; i !== e; ++i) {
        buffer[i] = buffer[originalValueOffset + (i % stride)];
      }
      this.cumulativeWeight = 0;
    },
    restoreOriginalState: function() {
      var originalValueOffset = this.valueSize * 3;
      this.binding.setValue(this.buffer, originalValueOffset);
    },
    _select: function(buffer, dstOffset, srcOffset, t, stride) {
      if (t >= 0.5) {
        for (var i = 0; i !== stride; ++i) {
          buffer[dstOffset + i] = buffer[srcOffset + i];
        }
      }
    },
    _slerp: function(buffer, dstOffset, srcOffset, t, stride) {
      THREE.Quaternion.slerpFlat(buffer, dstOffset, buffer, dstOffset, buffer, srcOffset, t);
    },
    _lerp: function(buffer, dstOffset, srcOffset, t, stride) {
      var s = 1 - t;
      for (var i = 0; i !== stride; ++i) {
        var j = dstOffset + i;
        buffer[j] = buffer[j] * s + buffer[srcOffset + i] * t;
      }
    }
  };
  THREE.BooleanKeyframeTrack = function(name, times, values) {
    THREE.KeyframeTrack.call(this, name, times, values);
  };
  THREE.BooleanKeyframeTrack.prototype = Object.assign(Object.create(THREE.KeyframeTrack.prototype), {
    constructor: THREE.BooleanKeyframeTrack,
    ValueTypeName: 'bool',
    ValueBufferType: Array,
    DefaultInterpolation: THREE.InterpolateDiscrete,
    InterpolantFactoryMethodLinear: undefined,
    InterpolantFactoryMethodSmooth: undefined
  });
  THREE.ColorKeyframeTrack = function(name, times, values, interpolation) {
    THREE.KeyframeTrack.call(this, name, times, values, interpolation);
  };
  THREE.ColorKeyframeTrack.prototype = Object.assign(Object.create(THREE.KeyframeTrack.prototype), {
    constructor: THREE.ColorKeyframeTrack,
    ValueTypeName: 'color'
  });
  THREE.NumberKeyframeTrack = function(name, times, values, interpolation) {
    THREE.KeyframeTrack.call(this, name, times, values, interpolation);
  };
  THREE.NumberKeyframeTrack.prototype = Object.assign(Object.create(THREE.KeyframeTrack.prototype), {
    constructor: THREE.NumberKeyframeTrack,
    ValueTypeName: 'number'
  });
  THREE.QuaternionKeyframeTrack = function(name, times, values, interpolation) {
    THREE.KeyframeTrack.call(this, name, times, values, interpolation);
  };
  THREE.QuaternionKeyframeTrack.prototype = Object.assign(Object.create(THREE.KeyframeTrack.prototype), {
    constructor: THREE.QuaternionKeyframeTrack,
    ValueTypeName: 'quaternion',
    DefaultInterpolation: THREE.InterpolateLinear,
    InterpolantFactoryMethodLinear: function(result) {
      return new THREE.QuaternionLinearInterpolant(this.times, this.values, this.getValueSize(), result);
    },
    InterpolantFactoryMethodSmooth: undefined
  });
  THREE.StringKeyframeTrack = function(name, times, values, interpolation) {
    THREE.KeyframeTrack.call(this, name, times, values, interpolation);
  };
  THREE.StringKeyframeTrack.prototype = Object.assign(Object.create(THREE.KeyframeTrack.prototype), {
    constructor: THREE.StringKeyframeTrack,
    ValueTypeName: 'string',
    ValueBufferType: Array,
    DefaultInterpolation: THREE.InterpolateDiscrete,
    InterpolantFactoryMethodLinear: undefined,
    InterpolantFactoryMethodSmooth: undefined
  });
  THREE.VectorKeyframeTrack = function(name, times, values, interpolation) {
    THREE.KeyframeTrack.call(this, name, times, values, interpolation);
  };
  THREE.VectorKeyframeTrack.prototype = Object.assign(Object.create(THREE.KeyframeTrack.prototype), {
    constructor: THREE.VectorKeyframeTrack,
    ValueTypeName: 'vector'
  });
  THREE.Audio = function(listener) {
    THREE.Object3D.call(this);
    this.type = 'Audio';
    this.context = listener.context;
    this.source = this.context.createBufferSource();
    this.source.onended = this.onEnded.bind(this);
    this.gain = this.context.createGain();
    this.gain.connect(listener.getInput());
    this.autoplay = false;
    this.startTime = 0;
    this.playbackRate = 1;
    this.isPlaying = false;
    this.hasPlaybackControl = true;
    this.sourceType = 'empty';
    this.filters = [];
  };
  THREE.Audio.prototype = Object.assign(Object.create(THREE.Object3D.prototype), {
    constructor: THREE.Audio,
    getOutput: function() {
      return this.gain;
    },
    setNodeSource: function(audioNode) {
      this.hasPlaybackControl = false;
      this.sourceType = 'audioNode';
      this.source = audioNode;
      this.connect();
      return this;
    },
    setBuffer: function(audioBuffer) {
      this.source.buffer = audioBuffer;
      this.sourceType = 'buffer';
      if (this.autoplay)
        this.play();
      return this;
    },
    play: function() {
      if (this.isPlaying === true) {
        console.warn('THREE.Audio: Audio is already playing.');
        return;
      }
      if (this.hasPlaybackControl === false) {
        console.warn('THREE.Audio: this Audio has no playback control.');
        return;
      }
      var source = this.context.createBufferSource();
      source.buffer = this.source.buffer;
      source.loop = this.source.loop;
      source.onended = this.source.onended;
      source.start(0, this.startTime);
      source.playbackRate.value = this.playbackRate;
      this.isPlaying = true;
      this.source = source;
      return this.connect();
    },
    pause: function() {
      if (this.hasPlaybackControl === false) {
        console.warn('THREE.Audio: this Audio has no playback control.');
        return;
      }
      this.source.stop();
      this.startTime = this.context.currentTime;
      this.isPlaying = false;
      return this;
    },
    stop: function() {
      if (this.hasPlaybackControl === false) {
        console.warn('THREE.Audio: this Audio has no playback control.');
        return;
      }
      this.source.stop();
      this.startTime = 0;
      this.isPlaying = false;
      return this;
    },
    connect: function() {
      if (this.filters.length > 0) {
        this.source.connect(this.filters[0]);
        for (var i = 1,
            l = this.filters.length; i < l; i++) {
          this.filters[i - 1].connect(this.filters[i]);
        }
        this.filters[this.filters.length - 1].connect(this.getOutput());
      } else {
        this.source.connect(this.getOutput());
      }
      return this;
    },
    disconnect: function() {
      if (this.filters.length > 0) {
        this.source.disconnect(this.filters[0]);
        for (var i = 1,
            l = this.filters.length; i < l; i++) {
          this.filters[i - 1].disconnect(this.filters[i]);
        }
        this.filters[this.filters.length - 1].disconnect(this.getOutput());
      } else {
        this.source.disconnect(this.getOutput());
      }
      return this;
    },
    getFilters: function() {
      return this.filters;
    },
    setFilters: function(value) {
      if (!value)
        value = [];
      if (this.isPlaying === true) {
        this.disconnect();
        this.filters = value;
        this.connect();
      } else {
        this.filters = value;
      }
      return this;
    },
    getFilter: function() {
      return this.getFilters()[0];
    },
    setFilter: function(filter) {
      return this.setFilters(filter ? [filter] : []);
    },
    setPlaybackRate: function(value) {
      if (this.hasPlaybackControl === false) {
        console.warn('THREE.Audio: this Audio has no playback control.');
        return;
      }
      this.playbackRate = value;
      if (this.isPlaying === true) {
        this.source.playbackRate.value = this.playbackRate;
      }
      return this;
    },
    getPlaybackRate: function() {
      return this.playbackRate;
    },
    onEnded: function() {
      this.isPlaying = false;
    },
    getLoop: function() {
      if (this.hasPlaybackControl === false) {
        console.warn('THREE.Audio: this Audio has no playback control.');
        return false;
      }
      return this.source.loop;
    },
    setLoop: function(value) {
      if (this.hasPlaybackControl === false) {
        console.warn('THREE.Audio: this Audio has no playback control.');
        return;
      }
      this.source.loop = value;
    },
    getVolume: function() {
      return this.gain.gain.value;
    },
    setVolume: function(value) {
      this.gain.gain.value = value;
      return this;
    }
  });
  THREE.AudioAnalyser = function(audio, fftSize) {
    this.analyser = audio.context.createAnalyser();
    this.analyser.fftSize = fftSize !== undefined ? fftSize : 2048;
    this.data = new Uint8Array(this.analyser.frequencyBinCount);
    audio.getOutput().connect(this.analyser);
  };
  Object.assign(THREE.AudioAnalyser.prototype, {
    getFrequencyData: function() {
      this.analyser.getByteFrequencyData(this.data);
      return this.data;
    },
    getAverageFrequency: function() {
      var value = 0,
          data = this.getFrequencyData();
      for (var i = 0; i < data.length; i++) {
        value += data[i];
      }
      return value / data.length;
    }
  });
  Object.defineProperty(THREE, 'AudioContext', {get: (function() {
      var context;
      return function get() {
        if (context === undefined) {
          context = new (window.AudioContext || window.webkitAudioContext)();
        }
        return context;
      };
    })()});
  THREE.PositionalAudio = function(listener) {
    THREE.Audio.call(this, listener);
    this.panner = this.context.createPanner();
    this.panner.connect(this.gain);
  };
  THREE.PositionalAudio.prototype = Object.assign(Object.create(THREE.Audio.prototype), {
    constructor: THREE.PositionalAudio,
    getOutput: function() {
      return this.panner;
    },
    getRefDistance: function() {
      return this.panner.refDistance;
    },
    setRefDistance: function(value) {
      this.panner.refDistance = value;
    },
    getRolloffFactor: function() {
      return this.panner.rolloffFactor;
    },
    setRolloffFactor: function(value) {
      this.panner.rolloffFactor = value;
    },
    getDistanceModel: function() {
      return this.panner.distanceModel;
    },
    setDistanceModel: function(value) {
      this.panner.distanceModel = value;
    },
    getMaxDistance: function() {
      return this.panner.maxDistance;
    },
    setMaxDistance: function(value) {
      this.panner.maxDistance = value;
    },
    updateMatrixWorld: (function() {
      var position = new THREE.Vector3();
      return function updateMatrixWorld(force) {
        THREE.Object3D.prototype.updateMatrixWorld.call(this, force);
        position.setFromMatrixPosition(this.matrixWorld);
        this.panner.setPosition(position.x, position.y, position.z);
      };
    })()
  });
  THREE.AudioListener = function() {
    THREE.Object3D.call(this);
    this.type = 'AudioListener';
    this.context = THREE.AudioContext;
    this.gain = this.context.createGain();
    this.gain.connect(this.context.destination);
    this.filter = null;
  };
  THREE.AudioListener.prototype = Object.assign(Object.create(THREE.Object3D.prototype), {
    constructor: THREE.AudioListener,
    getInput: function() {
      return this.gain;
    },
    removeFilter: function() {
      if (this.filter !== null) {
        this.gain.disconnect(this.filter);
        this.filter.disconnect(this.context.destination);
        this.gain.connect(this.context.destination);
        this.filter = null;
      }
    },
    getFilter: function() {
      return this.filter;
    },
    setFilter: function(value) {
      if (this.filter !== null) {
        this.gain.disconnect(this.filter);
        this.filter.disconnect(this.context.destination);
      } else {
        this.gain.disconnect(this.context.destination);
      }
      this.filter = value;
      this.gain.connect(this.filter);
      this.filter.connect(this.context.destination);
    },
    getMasterVolume: function() {
      return this.gain.gain.value;
    },
    setMasterVolume: function(value) {
      this.gain.gain.value = value;
    },
    updateMatrixWorld: (function() {
      var position = new THREE.Vector3();
      var quaternion = new THREE.Quaternion();
      var scale = new THREE.Vector3();
      var orientation = new THREE.Vector3();
      return function updateMatrixWorld(force) {
        THREE.Object3D.prototype.updateMatrixWorld.call(this, force);
        var listener = this.context.listener;
        var up = this.up;
        this.matrixWorld.decompose(position, quaternion, scale);
        orientation.set(0, 0, -1).applyQuaternion(quaternion);
        listener.setPosition(position.x, position.y, position.z);
        listener.setOrientation(orientation.x, orientation.y, orientation.z, up.x, up.y, up.z);
      };
    })()
  });
  THREE.Camera = function() {
    THREE.Object3D.call(this);
    this.type = 'Camera';
    this.matrixWorldInverse = new THREE.Matrix4();
    this.projectionMatrix = new THREE.Matrix4();
  };
  THREE.Camera.prototype = Object.create(THREE.Object3D.prototype);
  THREE.Camera.prototype.constructor = THREE.Camera;
  THREE.Camera.prototype.getWorldDirection = function() {
    var quaternion = new THREE.Quaternion();
    return function getWorldDirection(optionalTarget) {
      var result = optionalTarget || new THREE.Vector3();
      this.getWorldQuaternion(quaternion);
      return result.set(0, 0, -1).applyQuaternion(quaternion);
    };
  }();
  THREE.Camera.prototype.lookAt = function() {
    var m1 = new THREE.Matrix4();
    return function lookAt(vector) {
      m1.lookAt(this.position, vector, this.up);
      this.quaternion.setFromRotationMatrix(m1);
    };
  }();
  THREE.Camera.prototype.clone = function() {
    return new this.constructor().copy(this);
  };
  THREE.Camera.prototype.copy = function(source) {
    THREE.Object3D.prototype.copy.call(this, source);
    this.matrixWorldInverse.copy(source.matrixWorldInverse);
    this.projectionMatrix.copy(source.projectionMatrix);
    return this;
  };
  THREE.CubeCamera = function(near, far, cubeResolution) {
    THREE.Object3D.call(this);
    this.type = 'CubeCamera';
    var fov = 90,
        aspect = 1;
    var cameraPX = new THREE.PerspectiveCamera(fov, aspect, near, far);
    cameraPX.up.set(0, -1, 0);
    cameraPX.lookAt(new THREE.Vector3(1, 0, 0));
    this.add(cameraPX);
    var cameraNX = new THREE.PerspectiveCamera(fov, aspect, near, far);
    cameraNX.up.set(0, -1, 0);
    cameraNX.lookAt(new THREE.Vector3(-1, 0, 0));
    this.add(cameraNX);
    var cameraPY = new THREE.PerspectiveCamera(fov, aspect, near, far);
    cameraPY.up.set(0, 0, 1);
    cameraPY.lookAt(new THREE.Vector3(0, 1, 0));
    this.add(cameraPY);
    var cameraNY = new THREE.PerspectiveCamera(fov, aspect, near, far);
    cameraNY.up.set(0, 0, -1);
    cameraNY.lookAt(new THREE.Vector3(0, -1, 0));
    this.add(cameraNY);
    var cameraPZ = new THREE.PerspectiveCamera(fov, aspect, near, far);
    cameraPZ.up.set(0, -1, 0);
    cameraPZ.lookAt(new THREE.Vector3(0, 0, 1));
    this.add(cameraPZ);
    var cameraNZ = new THREE.PerspectiveCamera(fov, aspect, near, far);
    cameraNZ.up.set(0, -1, 0);
    cameraNZ.lookAt(new THREE.Vector3(0, 0, -1));
    this.add(cameraNZ);
    var options = {
      format: THREE.RGBFormat,
      magFilter: THREE.LinearFilter,
      minFilter: THREE.LinearFilter
    };
    this.renderTarget = new THREE.WebGLRenderTargetCube(cubeResolution, cubeResolution, options);
    this.updateCubeMap = function(renderer, scene) {
      if (this.parent === null)
        this.updateMatrixWorld();
      var renderTarget = this.renderTarget;
      var generateMipmaps = renderTarget.texture.generateMipmaps;
      renderTarget.texture.generateMipmaps = false;
      renderTarget.activeCubeFace = 0;
      renderer.render(scene, cameraPX, renderTarget);
      renderTarget.activeCubeFace = 1;
      renderer.render(scene, cameraNX, renderTarget);
      renderTarget.activeCubeFace = 2;
      renderer.render(scene, cameraPY, renderTarget);
      renderTarget.activeCubeFace = 3;
      renderer.render(scene, cameraNY, renderTarget);
      renderTarget.activeCubeFace = 4;
      renderer.render(scene, cameraPZ, renderTarget);
      renderTarget.texture.generateMipmaps = generateMipmaps;
      renderTarget.activeCubeFace = 5;
      renderer.render(scene, cameraNZ, renderTarget);
      renderer.setRenderTarget(null);
    };
  };
  THREE.CubeCamera.prototype = Object.create(THREE.Object3D.prototype);
  THREE.CubeCamera.prototype.constructor = THREE.CubeCamera;
  THREE.OrthographicCamera = function(left, right, top, bottom, near, far) {
    THREE.Camera.call(this);
    this.type = 'OrthographicCamera';
    this.zoom = 1;
    this.view = null;
    this.left = left;
    this.right = right;
    this.top = top;
    this.bottom = bottom;
    this.near = (near !== undefined) ? near : 0.1;
    this.far = (far !== undefined) ? far : 2000;
    this.updateProjectionMatrix();
  };
  THREE.OrthographicCamera.prototype = Object.assign(Object.create(THREE.Camera.prototype), {
    constructor: THREE.OrthographicCamera,
    copy: function(source) {
      THREE.Camera.prototype.copy.call(this, source);
      this.left = source.left;
      this.right = source.right;
      this.top = source.top;
      this.bottom = source.bottom;
      this.near = source.near;
      this.far = source.far;
      this.zoom = source.zoom;
      this.view = source.view === null ? null : Object.assign({}, source.view);
      return this;
    },
    setViewOffset: function(fullWidth, fullHeight, x, y, width, height) {
      this.view = {
        fullWidth: fullWidth,
        fullHeight: fullHeight,
        offsetX: x,
        offsetY: y,
        width: width,
        height: height
      };
      this.updateProjectionMatrix();
    },
    clearViewOffset: function() {
      this.view = null;
      this.updateProjectionMatrix();
    },
    updateProjectionMatrix: function() {
      var dx = (this.right - this.left) / (2 * this.zoom);
      var dy = (this.top - this.bottom) / (2 * this.zoom);
      var cx = (this.right + this.left) / 2;
      var cy = (this.top + this.bottom) / 2;
      var left = cx - dx;
      var right = cx + dx;
      var top = cy + dy;
      var bottom = cy - dy;
      if (this.view !== null) {
        var zoomW = this.zoom / (this.view.width / this.view.fullWidth);
        var zoomH = this.zoom / (this.view.height / this.view.fullHeight);
        var scaleW = (this.right - this.left) / this.view.width;
        var scaleH = (this.top - this.bottom) / this.view.height;
        left += scaleW * (this.view.offsetX / zoomW);
        right = left + scaleW * (this.view.width / zoomW);
        top -= scaleH * (this.view.offsetY / zoomH);
        bottom = top - scaleH * (this.view.height / zoomH);
      }
      this.projectionMatrix.makeOrthographic(left, right, top, bottom, this.near, this.far);
    },
    toJSON: function(meta) {
      var data = THREE.Object3D.prototype.toJSON.call(this, meta);
      data.object.zoom = this.zoom;
      data.object.left = this.left;
      data.object.right = this.right;
      data.object.top = this.top;
      data.object.bottom = this.bottom;
      data.object.near = this.near;
      data.object.far = this.far;
      if (this.view !== null)
        data.object.view = Object.assign({}, this.view);
      return data;
    }
  });
  THREE.PerspectiveCamera = function(fov, aspect, near, far) {
    THREE.Camera.call(this);
    this.type = 'PerspectiveCamera';
    this.fov = fov !== undefined ? fov : 50;
    this.zoom = 1;
    this.near = near !== undefined ? near : 0.1;
    this.far = far !== undefined ? far : 2000;
    this.focus = 10;
    this.aspect = aspect !== undefined ? aspect : 1;
    this.view = null;
    this.filmGauge = 35;
    this.filmOffset = 0;
    this.updateProjectionMatrix();
  };
  THREE.PerspectiveCamera.prototype = Object.assign(Object.create(THREE.Camera.prototype), {
    constructor: THREE.PerspectiveCamera,
    copy: function(source) {
      THREE.Camera.prototype.copy.call(this, source);
      this.fov = source.fov;
      this.zoom = source.zoom;
      this.near = source.near;
      this.far = source.far;
      this.focus = source.focus;
      this.aspect = source.aspect;
      this.view = source.view === null ? null : Object.assign({}, source.view);
      this.filmGauge = source.filmGauge;
      this.filmOffset = source.filmOffset;
      return this;
    },
    setFocalLength: function(focalLength) {
      var vExtentSlope = 0.5 * this.getFilmHeight() / focalLength;
      this.fov = THREE.Math.RAD2DEG * 2 * Math.atan(vExtentSlope);
      this.updateProjectionMatrix();
    },
    getFocalLength: function() {
      var vExtentSlope = Math.tan(THREE.Math.DEG2RAD * 0.5 * this.fov);
      return 0.5 * this.getFilmHeight() / vExtentSlope;
    },
    getEffectiveFOV: function() {
      return THREE.Math.RAD2DEG * 2 * Math.atan(Math.tan(THREE.Math.DEG2RAD * 0.5 * this.fov) / this.zoom);
    },
    getFilmWidth: function() {
      return this.filmGauge * Math.min(this.aspect, 1);
    },
    getFilmHeight: function() {
      return this.filmGauge / Math.max(this.aspect, 1);
    },
    setViewOffset: function(fullWidth, fullHeight, x, y, width, height) {
      this.aspect = fullWidth / fullHeight;
      this.view = {
        fullWidth: fullWidth,
        fullHeight: fullHeight,
        offsetX: x,
        offsetY: y,
        width: width,
        height: height
      };
      this.updateProjectionMatrix();
    },
    clearViewOffset: function() {
      this.view = null;
      this.updateProjectionMatrix();
    },
    updateProjectionMatrix: function() {
      var near = this.near,
          top = near * Math.tan(THREE.Math.DEG2RAD * 0.5 * this.fov) / this.zoom,
          height = 2 * top,
          width = this.aspect * height,
          left = -0.5 * width,
          view = this.view;
      if (view !== null) {
        var fullWidth = view.fullWidth,
            fullHeight = view.fullHeight;
        left += view.offsetX * width / fullWidth;
        top -= view.offsetY * height / fullHeight;
        width *= view.width / fullWidth;
        height *= view.height / fullHeight;
      }
      var skew = this.filmOffset;
      if (skew !== 0)
        left += near * skew / this.getFilmWidth();
      this.projectionMatrix.makeFrustum(left, left + width, top - height, top, near, this.far);
    },
    toJSON: function(meta) {
      var data = THREE.Object3D.prototype.toJSON.call(this, meta);
      data.object.fov = this.fov;
      data.object.zoom = this.zoom;
      data.object.near = this.near;
      data.object.far = this.far;
      data.object.focus = this.focus;
      data.object.aspect = this.aspect;
      if (this.view !== null)
        data.object.view = Object.assign({}, this.view);
      data.object.filmGauge = this.filmGauge;
      data.object.filmOffset = this.filmOffset;
      return data;
    }
  });
  THREE.StereoCamera = function() {
    this.type = 'StereoCamera';
    this.aspect = 1;
    this.cameraL = new THREE.PerspectiveCamera();
    this.cameraL.layers.enable(1);
    this.cameraL.matrixAutoUpdate = false;
    this.cameraR = new THREE.PerspectiveCamera();
    this.cameraR.layers.enable(2);
    this.cameraR.matrixAutoUpdate = false;
  };
  Object.assign(THREE.StereoCamera.prototype, {update: (function() {
      var focus,
          fov,
          aspect,
          near,
          far;
      var eyeRight = new THREE.Matrix4();
      var eyeLeft = new THREE.Matrix4();
      return function update(camera) {
        var needsUpdate = focus !== camera.focus || fov !== camera.fov || aspect !== camera.aspect * this.aspect || near !== camera.near || far !== camera.far;
        if (needsUpdate) {
          focus = camera.focus;
          fov = camera.fov;
          aspect = camera.aspect * this.aspect;
          near = camera.near;
          far = camera.far;
          var projectionMatrix = camera.projectionMatrix.clone();
          var eyeSep = 0.064 / 2;
          var eyeSepOnProjection = eyeSep * near / focus;
          var ymax = near * Math.tan(THREE.Math.DEG2RAD * fov * 0.5);
          var xmin,
              xmax;
          eyeLeft.elements[12] = -eyeSep;
          eyeRight.elements[12] = eyeSep;
          xmin = -ymax * aspect + eyeSepOnProjection;
          xmax = ymax * aspect + eyeSepOnProjection;
          projectionMatrix.elements[0] = 2 * near / (xmax - xmin);
          projectionMatrix.elements[8] = (xmax + xmin) / (xmax - xmin);
          this.cameraL.projectionMatrix.copy(projectionMatrix);
          xmin = -ymax * aspect - eyeSepOnProjection;
          xmax = ymax * aspect - eyeSepOnProjection;
          projectionMatrix.elements[0] = 2 * near / (xmax - xmin);
          projectionMatrix.elements[8] = (xmax + xmin) / (xmax - xmin);
          this.cameraR.projectionMatrix.copy(projectionMatrix);
        }
        this.cameraL.matrixWorld.copy(camera.matrixWorld).multiply(eyeLeft);
        this.cameraR.matrixWorld.copy(camera.matrixWorld).multiply(eyeRight);
      };
    })()});
  THREE.Light = function(color, intensity) {
    THREE.Object3D.call(this);
    this.type = 'Light';
    this.color = new THREE.Color(color);
    this.intensity = intensity !== undefined ? intensity : 1;
    this.receiveShadow = undefined;
  };
  THREE.Light.prototype = Object.assign(Object.create(THREE.Object3D.prototype), {
    constructor: THREE.Light,
    copy: function(source) {
      THREE.Object3D.prototype.copy.call(this, source);
      this.color.copy(source.color);
      this.intensity = source.intensity;
      return this;
    },
    toJSON: function(meta) {
      var data = THREE.Object3D.prototype.toJSON.call(this, meta);
      data.object.color = this.color.getHex();
      data.object.intensity = this.intensity;
      if (this.groundColor !== undefined)
        data.object.groundColor = this.groundColor.getHex();
      if (this.distance !== undefined)
        data.object.distance = this.distance;
      if (this.angle !== undefined)
        data.object.angle = this.angle;
      if (this.decay !== undefined)
        data.object.decay = this.decay;
      if (this.penumbra !== undefined)
        data.object.penumbra = this.penumbra;
      return data;
    }
  });
  THREE.LightShadow = function(camera) {
    this.camera = camera;
    this.bias = 0;
    this.radius = 1;
    this.mapSize = new THREE.Vector2(512, 512);
    this.map = null;
    this.matrix = new THREE.Matrix4();
  };
  Object.assign(THREE.LightShadow.prototype, {
    copy: function(source) {
      this.camera = source.camera.clone();
      this.bias = source.bias;
      this.radius = source.radius;
      this.mapSize.copy(source.mapSize);
      return this;
    },
    clone: function() {
      return new this.constructor().copy(this);
    }
  });
  THREE.AmbientLight = function(color, intensity) {
    THREE.Light.call(this, color, intensity);
    this.type = 'AmbientLight';
    this.castShadow = undefined;
  };
  THREE.AmbientLight.prototype = Object.assign(Object.create(THREE.Light.prototype), {constructor: THREE.AmbientLight});
  THREE.DirectionalLight = function(color, intensity) {
    THREE.Light.call(this, color, intensity);
    this.type = 'DirectionalLight';
    this.position.set(0, 1, 0);
    this.updateMatrix();
    this.target = new THREE.Object3D();
    this.shadow = new THREE.DirectionalLightShadow();
  };
  THREE.DirectionalLight.prototype = Object.assign(Object.create(THREE.Light.prototype), {
    constructor: THREE.DirectionalLight,
    copy: function(source) {
      THREE.Light.prototype.copy.call(this, source);
      this.target = source.target.clone();
      this.shadow = source.shadow.clone();
      return this;
    }
  });
  THREE.DirectionalLightShadow = function(light) {
    THREE.LightShadow.call(this, new THREE.OrthographicCamera(-5, 5, 5, -5, 0.5, 500));
  };
  THREE.DirectionalLightShadow.prototype = Object.assign(Object.create(THREE.LightShadow.prototype), {constructor: THREE.DirectionalLightShadow});
  THREE.HemisphereLight = function(skyColor, groundColor, intensity) {
    THREE.Light.call(this, skyColor, intensity);
    this.type = 'HemisphereLight';
    this.castShadow = undefined;
    this.position.set(0, 1, 0);
    this.updateMatrix();
    this.groundColor = new THREE.Color(groundColor);
  };
  THREE.HemisphereLight.prototype = Object.assign(Object.create(THREE.Light.prototype), {
    constructor: THREE.HemisphereLight,
    copy: function(source) {
      THREE.Light.prototype.copy.call(this, source);
      this.groundColor.copy(source.groundColor);
      return this;
    }
  });
  THREE.PointLight = function(color, intensity, distance, decay) {
    THREE.Light.call(this, color, intensity);
    this.type = 'PointLight';
    Object.defineProperty(this, 'power', {
      get: function() {
        return this.intensity * 4 * Math.PI;
      },
      set: function(power) {
        this.intensity = power / (4 * Math.PI);
      }
    });
    this.distance = (distance !== undefined) ? distance : 0;
    this.decay = (decay !== undefined) ? decay : 1;
    this.shadow = new THREE.LightShadow(new THREE.PerspectiveCamera(90, 1, 0.5, 500));
  };
  THREE.PointLight.prototype = Object.assign(Object.create(THREE.Light.prototype), {
    constructor: THREE.PointLight,
    copy: function(source) {
      THREE.Light.prototype.copy.call(this, source);
      this.distance = source.distance;
      this.decay = source.decay;
      this.shadow = source.shadow.clone();
      return this;
    }
  });
  THREE.SpotLight = function(color, intensity, distance, angle, penumbra, decay) {
    THREE.Light.call(this, color, intensity);
    this.type = 'SpotLight';
    this.position.set(0, 1, 0);
    this.updateMatrix();
    this.target = new THREE.Object3D();
    Object.defineProperty(this, 'power', {
      get: function() {
        return this.intensity * Math.PI;
      },
      set: function(power) {
        this.intensity = power / Math.PI;
      }
    });
    this.distance = (distance !== undefined) ? distance : 0;
    this.angle = (angle !== undefined) ? angle : Math.PI / 3;
    this.penumbra = (penumbra !== undefined) ? penumbra : 0;
    this.decay = (decay !== undefined) ? decay : 1;
    this.shadow = new THREE.SpotLightShadow();
  };
  THREE.SpotLight.prototype = Object.assign(Object.create(THREE.Light.prototype), {
    constructor: THREE.SpotLight,
    copy: function(source) {
      THREE.Light.prototype.copy.call(this, source);
      this.distance = source.distance;
      this.angle = source.angle;
      this.penumbra = source.penumbra;
      this.decay = source.decay;
      this.target = source.target.clone();
      this.shadow = source.shadow.clone();
      return this;
    }
  });
  THREE.SpotLightShadow = function() {
    THREE.LightShadow.call(this, new THREE.PerspectiveCamera(50, 1, 0.5, 500));
  };
  THREE.SpotLightShadow.prototype = Object.assign(Object.create(THREE.LightShadow.prototype), {
    constructor: THREE.SpotLightShadow,
    update: function(light) {
      var fov = THREE.Math.RAD2DEG * 2 * light.angle;
      var aspect = this.mapSize.width / this.mapSize.height;
      var far = light.distance || 500;
      var camera = this.camera;
      if (fov !== camera.fov || aspect !== camera.aspect || far !== camera.far) {
        camera.fov = fov;
        camera.aspect = aspect;
        camera.far = far;
        camera.updateProjectionMatrix();
      }
    }
  });
  THREE.AudioLoader = function(manager) {
    this.manager = (manager !== undefined) ? manager : THREE.DefaultLoadingManager;
  };
  Object.assign(THREE.AudioLoader.prototype, {load: function(url, onLoad, onProgress, onError) {
      var loader = new THREE.XHRLoader(this.manager);
      loader.setResponseType('arraybuffer');
      loader.load(url, function(buffer) {
        var context = THREE.AudioContext;
        context.decodeAudioData(buffer, function(audioBuffer) {
          onLoad(audioBuffer);
        });
      }, onProgress, onError);
    }});
  THREE.Cache = {
    enabled: false,
    files: {},
    add: function(key, file) {
      if (this.enabled === false)
        return;
      this.files[key] = file;
    },
    get: function(key) {
      if (this.enabled === false)
        return;
      return this.files[key];
    },
    remove: function(key) {
      delete this.files[key];
    },
    clear: function() {
      this.files = {};
    }
  };
  THREE.Loader = function() {
    this.onLoadStart = function() {};
    this.onLoadProgress = function() {};
    this.onLoadComplete = function() {};
  };
  THREE.Loader.prototype = {
    constructor: THREE.Loader,
    crossOrigin: undefined,
    extractUrlBase: function(url) {
      var parts = url.split('/');
      if (parts.length === 1)
        return './';
      parts.pop();
      return parts.join('/') + '/';
    },
    initMaterials: function(materials, texturePath, crossOrigin) {
      var array = [];
      for (var i = 0; i < materials.length; ++i) {
        array[i] = this.createMaterial(materials[i], texturePath, crossOrigin);
      }
      return array;
    },
    createMaterial: (function() {
      var color,
          textureLoader,
          materialLoader;
      return function createMaterial(m, texturePath, crossOrigin) {
        if (color === undefined)
          color = new THREE.Color();
        if (textureLoader === undefined)
          textureLoader = new THREE.TextureLoader();
        if (materialLoader === undefined)
          materialLoader = new THREE.MaterialLoader();
        var textures = {};
        function loadTexture(path, repeat, offset, wrap, anisotropy) {
          var fullPath = texturePath + path;
          var loader = THREE.Loader.Handlers.get(fullPath);
          var texture;
          if (loader !== null) {
            texture = loader.load(fullPath);
          } else {
            textureLoader.setCrossOrigin(crossOrigin);
            texture = textureLoader.load(fullPath);
          }
          if (repeat !== undefined) {
            texture.repeat.fromArray(repeat);
            if (repeat[0] !== 1)
              texture.wrapS = THREE.RepeatWrapping;
            if (repeat[1] !== 1)
              texture.wrapT = THREE.RepeatWrapping;
          }
          if (offset !== undefined) {
            texture.offset.fromArray(offset);
          }
          if (wrap !== undefined) {
            if (wrap[0] === 'repeat')
              texture.wrapS = THREE.RepeatWrapping;
            if (wrap[0] === 'mirror')
              texture.wrapS = THREE.MirroredRepeatWrapping;
            if (wrap[1] === 'repeat')
              texture.wrapT = THREE.RepeatWrapping;
            if (wrap[1] === 'mirror')
              texture.wrapT = THREE.MirroredRepeatWrapping;
          }
          if (anisotropy !== undefined) {
            texture.anisotropy = anisotropy;
          }
          var uuid = THREE.Math.generateUUID();
          textures[uuid] = texture;
          return uuid;
        }
        var json = {
          uuid: THREE.Math.generateUUID(),
          type: 'MeshLambertMaterial'
        };
        for (var name in m) {
          var value = m[name];
          switch (name) {
            case 'DbgColor':
            case 'DbgIndex':
            case 'opticalDensity':
            case 'illumination':
              break;
            case 'DbgName':
              json.name = value;
              break;
            case 'blending':
              json.blending = THREE[value];
              break;
            case 'colorAmbient':
            case 'mapAmbient':
              console.warn('THREE.Loader.createMaterial:', name, 'is no longer supported.');
              break;
            case 'colorDiffuse':
              json.color = color.fromArray(value).getHex();
              break;
            case 'colorSpecular':
              json.specular = color.fromArray(value).getHex();
              break;
            case 'colorEmissive':
              json.emissive = color.fromArray(value).getHex();
              break;
            case 'specularCoef':
              json.shininess = value;
              break;
            case 'shading':
              if (value.toLowerCase() === 'basic')
                json.type = 'MeshBasicMaterial';
              if (value.toLowerCase() === 'phong')
                json.type = 'MeshPhongMaterial';
              if (value.toLowerCase() === 'standard')
                json.type = 'MeshStandardMaterial';
              break;
            case 'mapDiffuse':
              json.map = loadTexture(value, m.mapDiffuseRepeat, m.mapDiffuseOffset, m.mapDiffuseWrap, m.mapDiffuseAnisotropy);
              break;
            case 'mapDiffuseRepeat':
            case 'mapDiffuseOffset':
            case 'mapDiffuseWrap':
            case 'mapDiffuseAnisotropy':
              break;
            case 'mapEmissive':
              json.emissiveMap = loadTexture(value, m.mapEmissiveRepeat, m.mapEmissiveOffset, m.mapEmissiveWrap, m.mapEmissiveAnisotropy);
              break;
            case 'mapEmissiveRepeat':
            case 'mapEmissiveOffset':
            case 'mapEmissiveWrap':
            case 'mapEmissiveAnisotropy':
              break;
            case 'mapLight':
              json.lightMap = loadTexture(value, m.mapLightRepeat, m.mapLightOffset, m.mapLightWrap, m.mapLightAnisotropy);
              break;
            case 'mapLightRepeat':
            case 'mapLightOffset':
            case 'mapLightWrap':
            case 'mapLightAnisotropy':
              break;
            case 'mapAO':
              json.aoMap = loadTexture(value, m.mapAORepeat, m.mapAOOffset, m.mapAOWrap, m.mapAOAnisotropy);
              break;
            case 'mapAORepeat':
            case 'mapAOOffset':
            case 'mapAOWrap':
            case 'mapAOAnisotropy':
              break;
            case 'mapBump':
              json.bumpMap = loadTexture(value, m.mapBumpRepeat, m.mapBumpOffset, m.mapBumpWrap, m.mapBumpAnisotropy);
              break;
            case 'mapBumpScale':
              json.bumpScale = value;
              break;
            case 'mapBumpRepeat':
            case 'mapBumpOffset':
            case 'mapBumpWrap':
            case 'mapBumpAnisotropy':
              break;
            case 'mapNormal':
              json.normalMap = loadTexture(value, m.mapNormalRepeat, m.mapNormalOffset, m.mapNormalWrap, m.mapNormalAnisotropy);
              break;
            case 'mapNormalFactor':
              json.normalScale = [value, value];
              break;
            case 'mapNormalRepeat':
            case 'mapNormalOffset':
            case 'mapNormalWrap':
            case 'mapNormalAnisotropy':
              break;
            case 'mapSpecular':
              json.specularMap = loadTexture(value, m.mapSpecularRepeat, m.mapSpecularOffset, m.mapSpecularWrap, m.mapSpecularAnisotropy);
              break;
            case 'mapSpecularRepeat':
            case 'mapSpecularOffset':
            case 'mapSpecularWrap':
            case 'mapSpecularAnisotropy':
              break;
            case 'mapMetalness':
              json.metalnessMap = loadTexture(value, m.mapMetalnessRepeat, m.mapMetalnessOffset, m.mapMetalnessWrap, m.mapMetalnessAnisotropy);
              break;
            case 'mapMetalnessRepeat':
            case 'mapMetalnessOffset':
            case 'mapMetalnessWrap':
            case 'mapMetalnessAnisotropy':
              break;
            case 'mapRoughness':
              json.roughnessMap = loadTexture(value, m.mapRoughnessRepeat, m.mapRoughnessOffset, m.mapRoughnessWrap, m.mapRoughnessAnisotropy);
              break;
            case 'mapRoughnessRepeat':
            case 'mapRoughnessOffset':
            case 'mapRoughnessWrap':
            case 'mapRoughnessAnisotropy':
              break;
            case 'mapAlpha':
              json.alphaMap = loadTexture(value, m.mapAlphaRepeat, m.mapAlphaOffset, m.mapAlphaWrap, m.mapAlphaAnisotropy);
              break;
            case 'mapAlphaRepeat':
            case 'mapAlphaOffset':
            case 'mapAlphaWrap':
            case 'mapAlphaAnisotropy':
              break;
            case 'flipSided':
              json.side = THREE.BackSide;
              break;
            case 'doubleSided':
              json.side = THREE.DoubleSide;
              break;
            case 'transparency':
              console.warn('THREE.Loader.createMaterial: transparency has been renamed to opacity');
              json.opacity = value;
              break;
            case 'depthTest':
            case 'depthWrite':
            case 'colorWrite':
            case 'opacity':
            case 'reflectivity':
            case 'transparent':
            case 'visible':
            case 'wireframe':
              json[name] = value;
              break;
            case 'vertexColors':
              if (value === true)
                json.vertexColors = THREE.VertexColors;
              if (value === 'face')
                json.vertexColors = THREE.FaceColors;
              break;
            default:
              console.error('THREE.Loader.createMaterial: Unsupported', name, value);
              break;
          }
        }
        if (json.type === 'MeshBasicMaterial')
          delete json.emissive;
        if (json.type !== 'MeshPhongMaterial')
          delete json.specular;
        if (json.opacity < 1)
          json.transparent = true;
        materialLoader.setTextures(textures);
        return materialLoader.parse(json);
      };
    })()
  };
  THREE.Loader.Handlers = {
    handlers: [],
    add: function(regex, loader) {
      this.handlers.push(regex, loader);
    },
    get: function(file) {
      var handlers = this.handlers;
      for (var i = 0,
          l = handlers.length; i < l; i += 2) {
        var regex = handlers[i];
        var loader = handlers[i + 1];
        if (regex.test(file)) {
          return loader;
        }
      }
      return null;
    }
  };
  THREE.XHRLoader = function(manager) {
    this.manager = (manager !== undefined) ? manager : THREE.DefaultLoadingManager;
  };
  Object.assign(THREE.XHRLoader.prototype, {
    load: function(url, onLoad, onProgress, onError) {
      if (this.path !== undefined)
        url = this.path + url;
      var scope = this;
      var cached = THREE.Cache.get(url);
      if (cached !== undefined) {
        if (onLoad) {
          setTimeout(function() {
            onLoad(cached);
          }, 0);
        }
        return cached;
      }
      var request = new XMLHttpRequest();
      request.overrideMimeType('text/plain');
      request.open('GET', url, true);
      request.addEventListener('load', function(event) {
        var response = event.target.response;
        THREE.Cache.add(url, response);
        if (this.status === 200) {
          if (onLoad)
            onLoad(response);
          scope.manager.itemEnd(url);
        } else if (this.status === 0) {
          console.warn('THREE.XHRLoader: HTTP Status 0 received.');
          if (onLoad)
            onLoad(response);
          scope.manager.itemEnd(url);
        } else {
          if (onError)
            onError(event);
          scope.manager.itemError(url);
        }
      }, false);
      if (onProgress !== undefined) {
        request.addEventListener('progress', function(event) {
          onProgress(event);
        }, false);
      }
      request.addEventListener('error', function(event) {
        if (onError)
          onError(event);
        scope.manager.itemError(url);
      }, false);
      if (this.responseType !== undefined)
        request.responseType = this.responseType;
      if (this.withCredentials !== undefined)
        request.withCredentials = this.withCredentials;
      request.send(null);
      scope.manager.itemStart(url);
      return request;
    },
    setPath: function(value) {
      this.path = value;
      return this;
    },
    setResponseType: function(value) {
      this.responseType = value;
      return this;
    },
    setWithCredentials: function(value) {
      this.withCredentials = value;
      return this;
    }
  });
  THREE.FontLoader = function(manager) {
    this.manager = (manager !== undefined) ? manager : THREE.DefaultLoadingManager;
  };
  Object.assign(THREE.FontLoader.prototype, {
    load: function(url, onLoad, onProgress, onError) {
      var scope = this;
      var loader = new THREE.XHRLoader(this.manager);
      loader.load(url, function(text) {
        var json;
        try {
          json = JSON.parse(text);
        } catch (e) {
          console.warn('THREE.FontLoader: typeface.js support is being deprecated. Use typeface.json instead.');
          json = JSON.parse(text.substring(65, text.length - 2));
        }
        var font = scope.parse(json);
        if (onLoad)
          onLoad(font);
      }, onProgress, onError);
    },
    parse: function(json) {
      return new THREE.Font(json);
    }
  });
  THREE.ImageLoader = function(manager) {
    this.manager = (manager !== undefined) ? manager : THREE.DefaultLoadingManager;
  };
  Object.assign(THREE.ImageLoader.prototype, {
    load: function(url, onLoad, onProgress, onError) {
      var image = document.createElementNS('http://www.w3.org/1999/xhtml', 'img');
      image.onload = function() {
        URL.revokeObjectURL(image.src);
        if (onLoad)
          onLoad(image);
      };
      if (url.indexOf('data:') === 0) {
        image.src = url;
      } else {
        var loader = new THREE.XHRLoader(this.manager);
        loader.setPath(this.path);
        loader.setResponseType('blob');
        loader.load(url, function(blob) {
          image.src = URL.createObjectURL(blob);
        }, onProgress, onError);
      }
      return image;
    },
    setCrossOrigin: function(value) {
      this.crossOrigin = value;
      return this;
    },
    setPath: function(value) {
      this.path = value;
      return this;
    }
  });
  THREE.JSONLoader = function(manager) {
    if (typeof manager === 'boolean') {
      console.warn('THREE.JSONLoader: showStatus parameter has been removed from constructor.');
      manager = undefined;
    }
    this.manager = (manager !== undefined) ? manager : THREE.DefaultLoadingManager;
    this.withCredentials = false;
  };
  Object.assign(THREE.JSONLoader.prototype, {
    load: function(url, onLoad, onProgress, onError) {
      var scope = this;
      var texturePath = this.texturePath && (typeof this.texturePath === "string") ? this.texturePath : THREE.Loader.prototype.extractUrlBase(url);
      var loader = new THREE.XHRLoader(this.manager);
      loader.setWithCredentials(this.withCredentials);
      loader.load(url, function(text) {
        var json = JSON.parse(text);
        var metadata = json.metadata;
        if (metadata !== undefined) {
          var type = metadata.type;
          if (type !== undefined) {
            if (type.toLowerCase() === 'object') {
              console.error('THREE.JSONLoader: ' + url + ' should be loaded with THREE.ObjectLoader instead.');
              return;
            }
            if (type.toLowerCase() === 'scene') {
              console.error('THREE.JSONLoader: ' + url + ' should be loaded with THREE.SceneLoader instead.');
              return;
            }
          }
        }
        var object = scope.parse(json, texturePath);
        onLoad(object.geometry, object.materials);
      }, onProgress, onError);
    },
    setTexturePath: function(value) {
      this.texturePath = value;
    },
    parse: function(json, texturePath) {
      var geometry = new THREE.Geometry(),
          scale = (json.scale !== undefined) ? 1.0 / json.scale : 1.0;
      parseModel(scale);
      parseSkin();
      parseMorphing(scale);
      parseAnimations();
      geometry.computeFaceNormals();
      geometry.computeBoundingSphere();
      function parseModel(scale) {
        function isBitSet(value, position) {
          return value & (1 << position);
        }
        var i,
            j,
            fi,
            offset,
            zLength,
            colorIndex,
            normalIndex,
            uvIndex,
            materialIndex,
            type,
            isQuad,
            hasMaterial,
            hasFaceVertexUv,
            hasFaceNormal,
            hasFaceVertexNormal,
            hasFaceColor,
            hasFaceVertexColor,
            vertex,
            face,
            faceA,
            faceB,
            hex,
            normal,
            uvLayer,
            uv,
            u,
            v,
            faces = json.faces,
            vertices = json.vertices,
            normals = json.normals,
            colors = json.colors,
            nUvLayers = 0;
        if (json.uvs !== undefined) {
          for (i = 0; i < json.uvs.length; i++) {
            if (json.uvs[i].length)
              nUvLayers++;
          }
          for (i = 0; i < nUvLayers; i++) {
            geometry.faceVertexUvs[i] = [];
          }
        }
        offset = 0;
        zLength = vertices.length;
        while (offset < zLength) {
          vertex = new THREE.Vector3();
          vertex.x = vertices[offset++] * scale;
          vertex.y = vertices[offset++] * scale;
          vertex.z = vertices[offset++] * scale;
          geometry.vertices.push(vertex);
        }
        offset = 0;
        zLength = faces.length;
        while (offset < zLength) {
          type = faces[offset++];
          isQuad = isBitSet(type, 0);
          hasMaterial = isBitSet(type, 1);
          hasFaceVertexUv = isBitSet(type, 3);
          hasFaceNormal = isBitSet(type, 4);
          hasFaceVertexNormal = isBitSet(type, 5);
          hasFaceColor = isBitSet(type, 6);
          hasFaceVertexColor = isBitSet(type, 7);
          if (isQuad) {
            faceA = new THREE.Face3();
            faceA.a = faces[offset];
            faceA.b = faces[offset + 1];
            faceA.c = faces[offset + 3];
            faceB = new THREE.Face3();
            faceB.a = faces[offset + 1];
            faceB.b = faces[offset + 2];
            faceB.c = faces[offset + 3];
            offset += 4;
            if (hasMaterial) {
              materialIndex = faces[offset++];
              faceA.materialIndex = materialIndex;
              faceB.materialIndex = materialIndex;
            }
            fi = geometry.faces.length;
            if (hasFaceVertexUv) {
              for (i = 0; i < nUvLayers; i++) {
                uvLayer = json.uvs[i];
                geometry.faceVertexUvs[i][fi] = [];
                geometry.faceVertexUvs[i][fi + 1] = [];
                for (j = 0; j < 4; j++) {
                  uvIndex = faces[offset++];
                  u = uvLayer[uvIndex * 2];
                  v = uvLayer[uvIndex * 2 + 1];
                  uv = new THREE.Vector2(u, v);
                  if (j !== 2)
                    geometry.faceVertexUvs[i][fi].push(uv);
                  if (j !== 0)
                    geometry.faceVertexUvs[i][fi + 1].push(uv);
                }
              }
            }
            if (hasFaceNormal) {
              normalIndex = faces[offset++] * 3;
              faceA.normal.set(normals[normalIndex++], normals[normalIndex++], normals[normalIndex]);
              faceB.normal.copy(faceA.normal);
            }
            if (hasFaceVertexNormal) {
              for (i = 0; i < 4; i++) {
                normalIndex = faces[offset++] * 3;
                normal = new THREE.Vector3(normals[normalIndex++], normals[normalIndex++], normals[normalIndex]);
                if (i !== 2)
                  faceA.vertexNormals.push(normal);
                if (i !== 0)
                  faceB.vertexNormals.push(normal);
              }
            }
            if (hasFaceColor) {
              colorIndex = faces[offset++];
              hex = colors[colorIndex];
              faceA.color.setHex(hex);
              faceB.color.setHex(hex);
            }
            if (hasFaceVertexColor) {
              for (i = 0; i < 4; i++) {
                colorIndex = faces[offset++];
                hex = colors[colorIndex];
                if (i !== 2)
                  faceA.vertexColors.push(new THREE.Color(hex));
                if (i !== 0)
                  faceB.vertexColors.push(new THREE.Color(hex));
              }
            }
            geometry.faces.push(faceA);
            geometry.faces.push(faceB);
          } else {
            face = new THREE.Face3();
            face.a = faces[offset++];
            face.b = faces[offset++];
            face.c = faces[offset++];
            if (hasMaterial) {
              materialIndex = faces[offset++];
              face.materialIndex = materialIndex;
            }
            fi = geometry.faces.length;
            if (hasFaceVertexUv) {
              for (i = 0; i < nUvLayers; i++) {
                uvLayer = json.uvs[i];
                geometry.faceVertexUvs[i][fi] = [];
                for (j = 0; j < 3; j++) {
                  uvIndex = faces[offset++];
                  u = uvLayer[uvIndex * 2];
                  v = uvLayer[uvIndex * 2 + 1];
                  uv = new THREE.Vector2(u, v);
                  geometry.faceVertexUvs[i][fi].push(uv);
                }
              }
            }
            if (hasFaceNormal) {
              normalIndex = faces[offset++] * 3;
              face.normal.set(normals[normalIndex++], normals[normalIndex++], normals[normalIndex]);
            }
            if (hasFaceVertexNormal) {
              for (i = 0; i < 3; i++) {
                normalIndex = faces[offset++] * 3;
                normal = new THREE.Vector3(normals[normalIndex++], normals[normalIndex++], normals[normalIndex]);
                face.vertexNormals.push(normal);
              }
            }
            if (hasFaceColor) {
              colorIndex = faces[offset++];
              face.color.setHex(colors[colorIndex]);
            }
            if (hasFaceVertexColor) {
              for (i = 0; i < 3; i++) {
                colorIndex = faces[offset++];
                face.vertexColors.push(new THREE.Color(colors[colorIndex]));
              }
            }
            geometry.faces.push(face);
          }
        }
      }
      function parseSkin() {
        var influencesPerVertex = (json.influencesPerVertex !== undefined) ? json.influencesPerVertex : 2;
        if (json.skinWeights) {
          for (var i = 0,
              l = json.skinWeights.length; i < l; i += influencesPerVertex) {
            var x = json.skinWeights[i];
            var y = (influencesPerVertex > 1) ? json.skinWeights[i + 1] : 0;
            var z = (influencesPerVertex > 2) ? json.skinWeights[i + 2] : 0;
            var w = (influencesPerVertex > 3) ? json.skinWeights[i + 3] : 0;
            geometry.skinWeights.push(new THREE.Vector4(x, y, z, w));
          }
        }
        if (json.skinIndices) {
          for (var i = 0,
              l = json.skinIndices.length; i < l; i += influencesPerVertex) {
            var a = json.skinIndices[i];
            var b = (influencesPerVertex > 1) ? json.skinIndices[i + 1] : 0;
            var c = (influencesPerVertex > 2) ? json.skinIndices[i + 2] : 0;
            var d = (influencesPerVertex > 3) ? json.skinIndices[i + 3] : 0;
            geometry.skinIndices.push(new THREE.Vector4(a, b, c, d));
          }
        }
        geometry.bones = json.bones;
        if (geometry.bones && geometry.bones.length > 0 && (geometry.skinWeights.length !== geometry.skinIndices.length || geometry.skinIndices.length !== geometry.vertices.length)) {
          console.warn('When skinning, number of vertices (' + geometry.vertices.length + '), skinIndices (' + geometry.skinIndices.length + '), and skinWeights (' + geometry.skinWeights.length + ') should match.');
        }
      }
      function parseMorphing(scale) {
        if (json.morphTargets !== undefined) {
          for (var i = 0,
              l = json.morphTargets.length; i < l; i++) {
            geometry.morphTargets[i] = {};
            geometry.morphTargets[i].name = json.morphTargets[i].name;
            geometry.morphTargets[i].vertices = [];
            var dstVertices = geometry.morphTargets[i].vertices;
            var srcVertices = json.morphTargets[i].vertices;
            for (var v = 0,
                vl = srcVertices.length; v < vl; v += 3) {
              var vertex = new THREE.Vector3();
              vertex.x = srcVertices[v] * scale;
              vertex.y = srcVertices[v + 1] * scale;
              vertex.z = srcVertices[v + 2] * scale;
              dstVertices.push(vertex);
            }
          }
        }
        if (json.morphColors !== undefined && json.morphColors.length > 0) {
          console.warn('THREE.JSONLoader: "morphColors" no longer supported. Using them as face colors.');
          var faces = geometry.faces;
          var morphColors = json.morphColors[0].colors;
          for (var i = 0,
              l = faces.length; i < l; i++) {
            faces[i].color.fromArray(morphColors, i * 3);
          }
        }
      }
      function parseAnimations() {
        var outputAnimations = [];
        var animations = [];
        if (json.animation !== undefined) {
          animations.push(json.animation);
        }
        if (json.animations !== undefined) {
          if (json.animations.length) {
            animations = animations.concat(json.animations);
          } else {
            animations.push(json.animations);
          }
        }
        for (var i = 0; i < animations.length; i++) {
          var clip = THREE.AnimationClip.parseAnimation(animations[i], geometry.bones);
          if (clip)
            outputAnimations.push(clip);
        }
        if (geometry.morphTargets) {
          var morphAnimationClips = THREE.AnimationClip.CreateClipsFromMorphTargetSequences(geometry.morphTargets, 10);
          outputAnimations = outputAnimations.concat(morphAnimationClips);
        }
        if (outputAnimations.length > 0)
          geometry.animations = outputAnimations;
      }
      if (json.materials === undefined || json.materials.length === 0) {
        return {geometry: geometry};
      } else {
        var materials = THREE.Loader.prototype.initMaterials(json.materials, texturePath, this.crossOrigin);
        return {
          geometry: geometry,
          materials: materials
        };
      }
    }
  });
  THREE.LoadingManager = function(onLoad, onProgress, onError) {
    var scope = this;
    var isLoading = false,
        itemsLoaded = 0,
        itemsTotal = 0;
    this.onStart = undefined;
    this.onLoad = onLoad;
    this.onProgress = onProgress;
    this.onError = onError;
    this.itemStart = function(url) {
      itemsTotal++;
      if (isLoading === false) {
        if (scope.onStart !== undefined) {
          scope.onStart(url, itemsLoaded, itemsTotal);
        }
      }
      isLoading = true;
    };
    this.itemEnd = function(url) {
      itemsLoaded++;
      if (scope.onProgress !== undefined) {
        scope.onProgress(url, itemsLoaded, itemsTotal);
      }
      if (itemsLoaded === itemsTotal) {
        isLoading = false;
        if (scope.onLoad !== undefined) {
          scope.onLoad();
        }
      }
    };
    this.itemError = function(url) {
      if (scope.onError !== undefined) {
        scope.onError(url);
      }
    };
  };
  THREE.DefaultLoadingManager = new THREE.LoadingManager();
  THREE.BufferGeometryLoader = function(manager) {
    this.manager = (manager !== undefined) ? manager : THREE.DefaultLoadingManager;
  };
  Object.assign(THREE.BufferGeometryLoader.prototype, {
    load: function(url, onLoad, onProgress, onError) {
      var scope = this;
      var loader = new THREE.XHRLoader(scope.manager);
      loader.load(url, function(text) {
        onLoad(scope.parse(JSON.parse(text)));
      }, onProgress, onError);
    },
    parse: function(json) {
      var geometry = new THREE.BufferGeometry();
      var index = json.data.index;
      var TYPED_ARRAYS = {
        'Int8Array': Int8Array,
        'Uint8Array': Uint8Array,
        'Uint8ClampedArray': Uint8ClampedArray,
        'Int16Array': Int16Array,
        'Uint16Array': Uint16Array,
        'Int32Array': Int32Array,
        'Uint32Array': Uint32Array,
        'Float32Array': Float32Array,
        'Float64Array': Float64Array
      };
      if (index !== undefined) {
        var typedArray = new TYPED_ARRAYS[index.type](index.array);
        geometry.setIndex(new THREE.BufferAttribute(typedArray, 1));
      }
      var attributes = json.data.attributes;
      for (var key in attributes) {
        var attribute = attributes[key];
        var typedArray = new TYPED_ARRAYS[attribute.type](attribute.array);
        geometry.addAttribute(key, new THREE.BufferAttribute(typedArray, attribute.itemSize, attribute.normalized));
      }
      var groups = json.data.groups || json.data.drawcalls || json.data.offsets;
      if (groups !== undefined) {
        for (var i = 0,
            n = groups.length; i !== n; ++i) {
          var group = groups[i];
          geometry.addGroup(group.start, group.count, group.materialIndex);
        }
      }
      var boundingSphere = json.data.boundingSphere;
      if (boundingSphere !== undefined) {
        var center = new THREE.Vector3();
        if (boundingSphere.center !== undefined) {
          center.fromArray(boundingSphere.center);
        }
        geometry.boundingSphere = new THREE.Sphere(center, boundingSphere.radius);
      }
      return geometry;
    }
  });
  THREE.MaterialLoader = function(manager) {
    this.manager = (manager !== undefined) ? manager : THREE.DefaultLoadingManager;
    this.textures = {};
  };
  Object.assign(THREE.MaterialLoader.prototype, {
    load: function(url, onLoad, onProgress, onError) {
      var scope = this;
      var loader = new THREE.XHRLoader(scope.manager);
      loader.load(url, function(text) {
        onLoad(scope.parse(JSON.parse(text)));
      }, onProgress, onError);
    },
    setTextures: function(value) {
      this.textures = value;
    },
    getTexture: function(name) {
      var textures = this.textures;
      if (textures[name] === undefined) {
        console.warn('THREE.MaterialLoader: Undefined texture', name);
      }
      return textures[name];
    },
    parse: function(json) {
      var material = new THREE[json.type];
      if (json.uuid !== undefined)
        material.uuid = json.uuid;
      if (json.name !== undefined)
        material.name = json.name;
      if (json.color !== undefined)
        material.color.setHex(json.color);
      if (json.roughness !== undefined)
        material.roughness = json.roughness;
      if (json.metalness !== undefined)
        material.metalness = json.metalness;
      if (json.emissive !== undefined)
        material.emissive.setHex(json.emissive);
      if (json.specular !== undefined)
        material.specular.setHex(json.specular);
      if (json.shininess !== undefined)
        material.shininess = json.shininess;
      if (json.uniforms !== undefined)
        material.uniforms = json.uniforms;
      if (json.vertexShader !== undefined)
        material.vertexShader = json.vertexShader;
      if (json.fragmentShader !== undefined)
        material.fragmentShader = json.fragmentShader;
      if (json.vertexColors !== undefined)
        material.vertexColors = json.vertexColors;
      if (json.shading !== undefined)
        material.shading = json.shading;
      if (json.blending !== undefined)
        material.blending = json.blending;
      if (json.side !== undefined)
        material.side = json.side;
      if (json.opacity !== undefined)
        material.opacity = json.opacity;
      if (json.transparent !== undefined)
        material.transparent = json.transparent;
      if (json.alphaTest !== undefined)
        material.alphaTest = json.alphaTest;
      if (json.depthTest !== undefined)
        material.depthTest = json.depthTest;
      if (json.depthWrite !== undefined)
        material.depthWrite = json.depthWrite;
      if (json.colorWrite !== undefined)
        material.colorWrite = json.colorWrite;
      if (json.wireframe !== undefined)
        material.wireframe = json.wireframe;
      if (json.wireframeLinewidth !== undefined)
        material.wireframeLinewidth = json.wireframeLinewidth;
      if (json.size !== undefined)
        material.size = json.size;
      if (json.sizeAttenuation !== undefined)
        material.sizeAttenuation = json.sizeAttenuation;
      if (json.map !== undefined)
        material.map = this.getTexture(json.map);
      if (json.alphaMap !== undefined) {
        material.alphaMap = this.getTexture(json.alphaMap);
        material.transparent = true;
      }
      if (json.bumpMap !== undefined)
        material.bumpMap = this.getTexture(json.bumpMap);
      if (json.bumpScale !== undefined)
        material.bumpScale = json.bumpScale;
      if (json.normalMap !== undefined)
        material.normalMap = this.getTexture(json.normalMap);
      if (json.normalScale !== undefined) {
        var normalScale = json.normalScale;
        if (Array.isArray(normalScale) === false) {
          normalScale = [normalScale, normalScale];
        }
        material.normalScale = new THREE.Vector2().fromArray(normalScale);
      }
      if (json.displacementMap !== undefined)
        material.displacementMap = this.getTexture(json.displacementMap);
      if (json.displacementScale !== undefined)
        material.displacementScale = json.displacementScale;
      if (json.displacementBias !== undefined)
        material.displacementBias = json.displacementBias;
      if (json.roughnessMap !== undefined)
        material.roughnessMap = this.getTexture(json.roughnessMap);
      if (json.metalnessMap !== undefined)
        material.metalnessMap = this.getTexture(json.metalnessMap);
      if (json.emissiveMap !== undefined)
        material.emissiveMap = this.getTexture(json.emissiveMap);
      if (json.emissiveIntensity !== undefined)
        material.emissiveIntensity = json.emissiveIntensity;
      if (json.specularMap !== undefined)
        material.specularMap = this.getTexture(json.specularMap);
      if (json.envMap !== undefined) {
        material.envMap = this.getTexture(json.envMap);
        material.combine = THREE.MultiplyOperation;
      }
      if (json.reflectivity !== undefined)
        material.reflectivity = json.reflectivity;
      if (json.lightMap !== undefined)
        material.lightMap = this.getTexture(json.lightMap);
      if (json.lightMapIntensity !== undefined)
        material.lightMapIntensity = json.lightMapIntensity;
      if (json.aoMap !== undefined)
        material.aoMap = this.getTexture(json.aoMap);
      if (json.aoMapIntensity !== undefined)
        material.aoMapIntensity = json.aoMapIntensity;
      if (json.materials !== undefined) {
        for (var i = 0,
            l = json.materials.length; i < l; i++) {
          material.materials.push(this.parse(json.materials[i]));
        }
      }
      return material;
    }
  });
  THREE.ObjectLoader = function(manager) {
    this.manager = (manager !== undefined) ? manager : THREE.DefaultLoadingManager;
    this.texturePath = '';
  };
  Object.assign(THREE.ObjectLoader.prototype, {
    load: function(url, onLoad, onProgress, onError) {
      if (this.texturePath === '') {
        this.texturePath = url.substring(0, url.lastIndexOf('/') + 1);
      }
      var scope = this;
      var loader = new THREE.XHRLoader(scope.manager);
      loader.load(url, function(text) {
        scope.parse(JSON.parse(text), onLoad);
      }, onProgress, onError);
    },
    setTexturePath: function(value) {
      this.texturePath = value;
    },
    setCrossOrigin: function(value) {
      this.crossOrigin = value;
    },
    parse: function(json, onLoad) {
      var geometries = this.parseGeometries(json.geometries);
      var images = this.parseImages(json.images, function() {
        if (onLoad !== undefined)
          onLoad(object);
      });
      var textures = this.parseTextures(json.textures, images);
      var materials = this.parseMaterials(json.materials, textures);
      var object = this.parseObject(json.object, geometries, materials);
      if (json.animations) {
        object.animations = this.parseAnimations(json.animations);
      }
      if (json.images === undefined || json.images.length === 0) {
        if (onLoad !== undefined)
          onLoad(object);
      }
      return object;
    },
    parseGeometries: function(json) {
      var geometries = {};
      if (json !== undefined) {
        var geometryLoader = new THREE.JSONLoader();
        var bufferGeometryLoader = new THREE.BufferGeometryLoader();
        for (var i = 0,
            l = json.length; i < l; i++) {
          var geometry;
          var data = json[i];
          switch (data.type) {
            case 'PlaneGeometry':
            case 'PlaneBufferGeometry':
              geometry = new THREE[data.type](data.width, data.height, data.widthSegments, data.heightSegments);
              break;
            case 'BoxGeometry':
            case 'BoxBufferGeometry':
            case 'CubeGeometry':
              geometry = new THREE[data.type](data.width, data.height, data.depth, data.widthSegments, data.heightSegments, data.depthSegments);
              break;
            case 'CircleGeometry':
            case 'CircleBufferGeometry':
              geometry = new THREE[data.type](data.radius, data.segments, data.thetaStart, data.thetaLength);
              break;
            case 'CylinderGeometry':
            case 'CylinderBufferGeometry':
              geometry = new THREE[data.type](data.radiusTop, data.radiusBottom, data.height, data.radialSegments, data.heightSegments, data.openEnded, data.thetaStart, data.thetaLength);
              break;
            case 'ConeGeometry':
            case 'ConeBufferGeometry':
              geometry = new THREE[data.type](data.radius, data.height, data.radialSegments, data.heightSegments, data.openEnded, data.thetaStart, data.thetaLength);
              break;
            case 'SphereGeometry':
            case 'SphereBufferGeometry':
              geometry = new THREE[data.type](data.radius, data.widthSegments, data.heightSegments, data.phiStart, data.phiLength, data.thetaStart, data.thetaLength);
              break;
            case 'DodecahedronGeometry':
            case 'IcosahedronGeometry':
            case 'OctahedronGeometry':
            case 'TetrahedronGeometry':
              geometry = new THREE[data.type](data.radius, data.detail);
              break;
            case 'RingGeometry':
            case 'RingBufferGeometry':
              geometry = new THREE[data.type](data.innerRadius, data.outerRadius, data.thetaSegments, data.phiSegments, data.thetaStart, data.thetaLength);
              break;
            case 'TorusGeometry':
            case 'TorusBufferGeometry':
              geometry = new THREE[data.type](data.radius, data.tube, data.radialSegments, data.tubularSegments, data.arc);
              break;
            case 'TorusKnotGeometry':
            case 'TorusKnotBufferGeometry':
              geometry = new THREE[data.type](data.radius, data.tube, data.tubularSegments, data.radialSegments, data.p, data.q);
              break;
            case 'LatheGeometry':
            case 'LatheBufferGeometry':
              geometry = new THREE[data.type](data.points, data.segments, data.phiStart, data.phiLength);
              break;
            case 'BufferGeometry':
              geometry = bufferGeometryLoader.parse(data);
              break;
            case 'Geometry':
              geometry = geometryLoader.parse(data.data, this.texturePath).geometry;
              break;
            default:
              console.warn('THREE.ObjectLoader: Unsupported geometry type "' + data.type + '"');
              continue;
          }
          geometry.uuid = data.uuid;
          if (data.name !== undefined)
            geometry.name = data.name;
          geometries[data.uuid] = geometry;
        }
      }
      return geometries;
    },
    parseMaterials: function(json, textures) {
      var materials = {};
      if (json !== undefined) {
        var loader = new THREE.MaterialLoader();
        loader.setTextures(textures);
        for (var i = 0,
            l = json.length; i < l; i++) {
          var material = loader.parse(json[i]);
          materials[material.uuid] = material;
        }
      }
      return materials;
    },
    parseAnimations: function(json) {
      var animations = [];
      for (var i = 0; i < json.length; i++) {
        var clip = THREE.AnimationClip.parse(json[i]);
        animations.push(clip);
      }
      return animations;
    },
    parseImages: function(json, onLoad) {
      var scope = this;
      var images = {};
      function loadImage(url) {
        scope.manager.itemStart(url);
        return loader.load(url, function() {
          scope.manager.itemEnd(url);
        });
      }
      if (json !== undefined && json.length > 0) {
        var manager = new THREE.LoadingManager(onLoad);
        var loader = new THREE.ImageLoader(manager);
        loader.setCrossOrigin(this.crossOrigin);
        for (var i = 0,
            l = json.length; i < l; i++) {
          var image = json[i];
          var path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test(image.url) ? image.url : scope.texturePath + image.url;
          images[image.uuid] = loadImage(path);
        }
      }
      return images;
    },
    parseTextures: function(json, images) {
      function parseConstant(value) {
        if (typeof(value) === 'number')
          return value;
        console.warn('THREE.ObjectLoader.parseTexture: Constant should be in numeric form.', value);
        return THREE[value];
      }
      var textures = {};
      if (json !== undefined) {
        for (var i = 0,
            l = json.length; i < l; i++) {
          var data = json[i];
          if (data.image === undefined) {
            console.warn('THREE.ObjectLoader: No "image" specified for', data.uuid);
          }
          if (images[data.image] === undefined) {
            console.warn('THREE.ObjectLoader: Undefined image', data.image);
          }
          var texture = new THREE.Texture(images[data.image]);
          texture.needsUpdate = true;
          texture.uuid = data.uuid;
          if (data.name !== undefined)
            texture.name = data.name;
          if (data.mapping !== undefined)
            texture.mapping = parseConstant(data.mapping);
          if (data.offset !== undefined)
            texture.offset = new THREE.Vector2(data.offset[0], data.offset[1]);
          if (data.repeat !== undefined)
            texture.repeat = new THREE.Vector2(data.repeat[0], data.repeat[1]);
          if (data.minFilter !== undefined)
            texture.minFilter = parseConstant(data.minFilter);
          if (data.magFilter !== undefined)
            texture.magFilter = parseConstant(data.magFilter);
          if (data.anisotropy !== undefined)
            texture.anisotropy = data.anisotropy;
          if (Array.isArray(data.wrap)) {
            texture.wrapS = parseConstant(data.wrap[0]);
            texture.wrapT = parseConstant(data.wrap[1]);
          }
          textures[data.uuid] = texture;
        }
      }
      return textures;
    },
    parseObject: function() {
      var matrix = new THREE.Matrix4();
      return function parseObject(data, geometries, materials) {
        var object;
        function getGeometry(name) {
          if (geometries[name] === undefined) {
            console.warn('THREE.ObjectLoader: Undefined geometry', name);
          }
          return geometries[name];
        }
        function getMaterial(name) {
          if (name === undefined)
            return undefined;
          if (materials[name] === undefined) {
            console.warn('THREE.ObjectLoader: Undefined material', name);
          }
          return materials[name];
        }
        switch (data.type) {
          case 'Scene':
            object = new THREE.Scene();
            break;
          case 'PerspectiveCamera':
            object = new THREE.PerspectiveCamera(data.fov, data.aspect, data.near, data.far);
            if (data.focus !== undefined)
              object.focus = data.focus;
            if (data.zoom !== undefined)
              object.zoom = data.zoom;
            if (data.filmGauge !== undefined)
              object.filmGauge = data.filmGauge;
            if (data.filmOffset !== undefined)
              object.filmOffset = data.filmOffset;
            if (data.view !== undefined)
              object.view = Object.assign({}, data.view);
            break;
          case 'OrthographicCamera':
            object = new THREE.OrthographicCamera(data.left, data.right, data.top, data.bottom, data.near, data.far);
            break;
          case 'AmbientLight':
            object = new THREE.AmbientLight(data.color, data.intensity);
            break;
          case 'DirectionalLight':
            object = new THREE.DirectionalLight(data.color, data.intensity);
            break;
          case 'PointLight':
            object = new THREE.PointLight(data.color, data.intensity, data.distance, data.decay);
            break;
          case 'SpotLight':
            object = new THREE.SpotLight(data.color, data.intensity, data.distance, data.angle, data.penumbra, data.decay);
            break;
          case 'HemisphereLight':
            object = new THREE.HemisphereLight(data.color, data.groundColor, data.intensity);
            break;
          case 'Mesh':
            var geometry = getGeometry(data.geometry);
            var material = getMaterial(data.material);
            if (geometry.bones && geometry.bones.length > 0) {
              object = new THREE.SkinnedMesh(geometry, material);
            } else {
              object = new THREE.Mesh(geometry, material);
            }
            break;
          case 'LOD':
            object = new THREE.LOD();
            break;
          case 'Line':
            object = new THREE.Line(getGeometry(data.geometry), getMaterial(data.material), data.mode);
            break;
          case 'PointCloud':
          case 'Points':
            object = new THREE.Points(getGeometry(data.geometry), getMaterial(data.material));
            break;
          case 'Sprite':
            object = new THREE.Sprite(getMaterial(data.material));
            break;
          case 'Group':
            object = new THREE.Group();
            break;
          default:
            object = new THREE.Object3D();
        }
        object.uuid = data.uuid;
        if (data.name !== undefined)
          object.name = data.name;
        if (data.matrix !== undefined) {
          matrix.fromArray(data.matrix);
          matrix.decompose(object.position, object.quaternion, object.scale);
        } else {
          if (data.position !== undefined)
            object.position.fromArray(data.position);
          if (data.rotation !== undefined)
            object.rotation.fromArray(data.rotation);
          if (data.scale !== undefined)
            object.scale.fromArray(data.scale);
        }
        if (data.castShadow !== undefined)
          object.castShadow = data.castShadow;
        if (data.receiveShadow !== undefined)
          object.receiveShadow = data.receiveShadow;
        if (data.visible !== undefined)
          object.visible = data.visible;
        if (data.userData !== undefined)
          object.userData = data.userData;
        if (data.children !== undefined) {
          for (var child in data.children) {
            object.add(this.parseObject(data.children[child], geometries, materials));
          }
        }
        if (data.type === 'LOD') {
          var levels = data.levels;
          for (var l = 0; l < levels.length; l++) {
            var level = levels[l];
            var child = object.getObjectByProperty('uuid', level.object);
            if (child !== undefined) {
              object.addLevel(child, level.distance);
            }
          }
        }
        return object;
      };
    }()
  });
  THREE.TextureLoader = function(manager) {
    this.manager = (manager !== undefined) ? manager : THREE.DefaultLoadingManager;
  };
  Object.assign(THREE.TextureLoader.prototype, {
    load: function(url, onLoad, onProgress, onError) {
      var texture = new THREE.Texture();
      var loader = new THREE.ImageLoader(this.manager);
      loader.setCrossOrigin(this.crossOrigin);
      loader.setPath(this.path);
      loader.load(url, function(image) {
        texture.image = image;
        texture.needsUpdate = true;
        if (onLoad !== undefined) {
          onLoad(texture);
        }
      }, onProgress, onError);
      return texture;
    },
    setCrossOrigin: function(value) {
      this.crossOrigin = value;
      return this;
    },
    setPath: function(value) {
      this.path = value;
      return this;
    }
  });
  THREE.CubeTextureLoader = function(manager) {
    this.manager = (manager !== undefined) ? manager : THREE.DefaultLoadingManager;
  };
  Object.assign(THREE.CubeTextureLoader.prototype, {
    load: function(urls, onLoad, onProgress, onError) {
      var texture = new THREE.CubeTexture();
      var loader = new THREE.ImageLoader(this.manager);
      loader.setCrossOrigin(this.crossOrigin);
      loader.setPath(this.path);
      var loaded = 0;
      function loadTexture(i) {
        loader.load(urls[i], function(image) {
          texture.images[i] = image;
          loaded++;
          if (loaded === 6) {
            texture.needsUpdate = true;
            if (onLoad)
              onLoad(texture);
          }
        }, undefined, onError);
      }
      for (var i = 0; i < urls.length; ++i) {
        loadTexture(i);
      }
      return texture;
    },
    setCrossOrigin: function(value) {
      this.crossOrigin = value;
      return this;
    },
    setPath: function(value) {
      this.path = value;
      return this;
    }
  });
  THREE.DataTextureLoader = THREE.BinaryTextureLoader = function(manager) {
    this.manager = (manager !== undefined) ? manager : THREE.DefaultLoadingManager;
    this._parser = null;
  };
  Object.assign(THREE.BinaryTextureLoader.prototype, {load: function(url, onLoad, onProgress, onError) {
      var scope = this;
      var texture = new THREE.DataTexture();
      var loader = new THREE.XHRLoader(this.manager);
      loader.setResponseType('arraybuffer');
      loader.load(url, function(buffer) {
        var texData = scope._parser(buffer);
        if (!texData)
          return;
        if (undefined !== texData.image) {
          texture.image = texData.image;
        } else if (undefined !== texData.data) {
          texture.image.width = texData.width;
          texture.image.height = texData.height;
          texture.image.data = texData.data;
        }
        texture.wrapS = undefined !== texData.wrapS ? texData.wrapS : THREE.ClampToEdgeWrapping;
        texture.wrapT = undefined !== texData.wrapT ? texData.wrapT : THREE.ClampToEdgeWrapping;
        texture.magFilter = undefined !== texData.magFilter ? texData.magFilter : THREE.LinearFilter;
        texture.minFilter = undefined !== texData.minFilter ? texData.minFilter : THREE.LinearMipMapLinearFilter;
        texture.anisotropy = undefined !== texData.anisotropy ? texData.anisotropy : 1;
        if (undefined !== texData.format) {
          texture.format = texData.format;
        }
        if (undefined !== texData.type) {
          texture.type = texData.type;
        }
        if (undefined !== texData.mipmaps) {
          texture.mipmaps = texData.mipmaps;
        }
        if (1 === texData.mipmapCount) {
          texture.minFilter = THREE.LinearFilter;
        }
        texture.needsUpdate = true;
        if (onLoad)
          onLoad(texture, texData);
      }, onProgress, onError);
      return texture;
    }});
  THREE.CompressedTextureLoader = function(manager) {
    this.manager = (manager !== undefined) ? manager : THREE.DefaultLoadingManager;
    this._parser = null;
  };
  Object.assign(THREE.CompressedTextureLoader.prototype, {
    load: function(url, onLoad, onProgress, onError) {
      var scope = this;
      var images = [];
      var texture = new THREE.CompressedTexture();
      texture.image = images;
      var loader = new THREE.XHRLoader(this.manager);
      loader.setPath(this.path);
      loader.setResponseType('arraybuffer');
      function loadTexture(i) {
        loader.load(url[i], function(buffer) {
          var texDatas = scope._parser(buffer, true);
          images[i] = {
            width: texDatas.width,
            height: texDatas.height,
            format: texDatas.format,
            mipmaps: texDatas.mipmaps
          };
          loaded += 1;
          if (loaded === 6) {
            if (texDatas.mipmapCount === 1)
              texture.minFilter = THREE.LinearFilter;
            texture.format = texDatas.format;
            texture.needsUpdate = true;
            if (onLoad)
              onLoad(texture);
          }
        }, onProgress, onError);
      }
      if (Array.isArray(url)) {
        var loaded = 0;
        for (var i = 0,
            il = url.length; i < il; ++i) {
          loadTexture(i);
        }
      } else {
        loader.load(url, function(buffer) {
          var texDatas = scope._parser(buffer, true);
          if (texDatas.isCubemap) {
            var faces = texDatas.mipmaps.length / texDatas.mipmapCount;
            for (var f = 0; f < faces; f++) {
              images[f] = {mipmaps: []};
              for (var i = 0; i < texDatas.mipmapCount; i++) {
                images[f].mipmaps.push(texDatas.mipmaps[f * texDatas.mipmapCount + i]);
                images[f].format = texDatas.format;
                images[f].width = texDatas.width;
                images[f].height = texDatas.height;
              }
            }
          } else {
            texture.image.width = texDatas.width;
            texture.image.height = texDatas.height;
            texture.mipmaps = texDatas.mipmaps;
          }
          if (texDatas.mipmapCount === 1) {
            texture.minFilter = THREE.LinearFilter;
          }
          texture.format = texDatas.format;
          texture.needsUpdate = true;
          if (onLoad)
            onLoad(texture);
        }, onProgress, onError);
      }
      return texture;
    },
    setPath: function(value) {
      this.path = value;
      return this;
    }
  });
  THREE.Material = function() {
    Object.defineProperty(this, 'id', {value: THREE.MaterialIdCount++});
    this.uuid = THREE.Math.generateUUID();
    this.name = '';
    this.type = 'Material';
    this.fog = true;
    this.lights = true;
    this.blending = THREE.NormalBlending;
    this.side = THREE.FrontSide;
    this.shading = THREE.SmoothShading;
    this.vertexColors = THREE.NoColors;
    this.opacity = 1;
    this.transparent = false;
    this.blendSrc = THREE.SrcAlphaFactor;
    this.blendDst = THREE.OneMinusSrcAlphaFactor;
    this.blendEquation = THREE.AddEquation;
    this.blendSrcAlpha = null;
    this.blendDstAlpha = null;
    this.blendEquationAlpha = null;
    this.depthFunc = THREE.LessEqualDepth;
    this.depthTest = true;
    this.depthWrite = true;
    this.clippingPlanes = null;
    this.clipShadows = false;
    this.colorWrite = true;
    this.precision = null;
    this.polygonOffset = false;
    this.polygonOffsetFactor = 0;
    this.polygonOffsetUnits = 0;
    this.alphaTest = 0;
    this.premultipliedAlpha = false;
    this.overdraw = 0;
    this.visible = true;
    this._needsUpdate = true;
  };
  THREE.Material.prototype = {
    constructor: THREE.Material,
    get needsUpdate() {
      return this._needsUpdate;
    },
    set needsUpdate(value) {
      if (value === true)
        this.update();
      this._needsUpdate = value;
    },
    setValues: function(values) {
      if (values === undefined)
        return;
      for (var key in values) {
        var newValue = values[key];
        if (newValue === undefined) {
          console.warn("THREE.Material: '" + key + "' parameter is undefined.");
          continue;
        }
        var currentValue = this[key];
        if (currentValue === undefined) {
          console.warn("THREE." + this.type + ": '" + key + "' is not a property of this material.");
          continue;
        }
        if (currentValue instanceof THREE.Color) {
          currentValue.set(newValue);
        } else if (currentValue instanceof THREE.Vector3 && newValue instanceof THREE.Vector3) {
          currentValue.copy(newValue);
        } else if (key === 'overdraw') {
          this[key] = Number(newValue);
        } else {
          this[key] = newValue;
        }
      }
    },
    toJSON: function(meta) {
      var isRoot = meta === undefined;
      if (isRoot) {
        meta = {
          textures: {},
          images: {}
        };
      }
      var data = {metadata: {
          version: 4.4,
          type: 'Material',
          generator: 'Material.toJSON'
        }};
      data.uuid = this.uuid;
      data.type = this.type;
      if (this.name !== '')
        data.name = this.name;
      if (this.color instanceof THREE.Color)
        data.color = this.color.getHex();
      if (this.roughness !== undefined)
        data.roughness = this.roughness;
      if (this.metalness !== undefined)
        data.metalness = this.metalness;
      if (this.emissive instanceof THREE.Color)
        data.emissive = this.emissive.getHex();
      if (this.specular instanceof THREE.Color)
        data.specular = this.specular.getHex();
      if (this.shininess !== undefined)
        data.shininess = this.shininess;
      if (this.map instanceof THREE.Texture)
        data.map = this.map.toJSON(meta).uuid;
      if (this.alphaMap instanceof THREE.Texture)
        data.alphaMap = this.alphaMap.toJSON(meta).uuid;
      if (this.lightMap instanceof THREE.Texture)
        data.lightMap = this.lightMap.toJSON(meta).uuid;
      if (this.bumpMap instanceof THREE.Texture) {
        data.bumpMap = this.bumpMap.toJSON(meta).uuid;
        data.bumpScale = this.bumpScale;
      }
      if (this.normalMap instanceof THREE.Texture) {
        data.normalMap = this.normalMap.toJSON(meta).uuid;
        data.normalScale = this.normalScale.toArray();
      }
      if (this.displacementMap instanceof THREE.Texture) {
        data.displacementMap = this.displacementMap.toJSON(meta).uuid;
        data.displacementScale = this.displacementScale;
        data.displacementBias = this.displacementBias;
      }
      if (this.roughnessMap instanceof THREE.Texture)
        data.roughnessMap = this.roughnessMap.toJSON(meta).uuid;
      if (this.metalnessMap instanceof THREE.Texture)
        data.metalnessMap = this.metalnessMap.toJSON(meta).uuid;
      if (this.emissiveMap instanceof THREE.Texture)
        data.emissiveMap = this.emissiveMap.toJSON(meta).uuid;
      if (this.specularMap instanceof THREE.Texture)
        data.specularMap = this.specularMap.toJSON(meta).uuid;
      if (this.envMap instanceof THREE.Texture) {
        data.envMap = this.envMap.toJSON(meta).uuid;
        data.reflectivity = this.reflectivity;
      }
      if (this.size !== undefined)
        data.size = this.size;
      if (this.sizeAttenuation !== undefined)
        data.sizeAttenuation = this.sizeAttenuation;
      if (this.blending !== THREE.NormalBlending)
        data.blending = this.blending;
      if (this.shading !== THREE.SmoothShading)
        data.shading = this.shading;
      if (this.side !== THREE.FrontSide)
        data.side = this.side;
      if (this.vertexColors !== THREE.NoColors)
        data.vertexColors = this.vertexColors;
      if (this.opacity < 1)
        data.opacity = this.opacity;
      if (this.transparent === true)
        data.transparent = this.transparent;
      if (this.alphaTest > 0)
        data.alphaTest = this.alphaTest;
      if (this.premultipliedAlpha === true)
        data.premultipliedAlpha = this.premultipliedAlpha;
      if (this.wireframe === true)
        data.wireframe = this.wireframe;
      if (this.wireframeLinewidth > 1)
        data.wireframeLinewidth = this.wireframeLinewidth;
      function extractFromCache(cache) {
        var values = [];
        for (var key in cache) {
          var data = cache[key];
          delete data.metadata;
          values.push(data);
        }
        return values;
      }
      if (isRoot) {
        var textures = extractFromCache(meta.textures);
        var images = extractFromCache(meta.images);
        if (textures.length > 0)
          data.textures = textures;
        if (images.length > 0)
          data.images = images;
      }
      return data;
    },
    clone: function() {
      return new this.constructor().copy(this);
    },
    copy: function(source) {
      this.name = source.name;
      this.fog = source.fog;
      this.lights = source.lights;
      this.blending = source.blending;
      this.side = source.side;
      this.shading = source.shading;
      this.vertexColors = source.vertexColors;
      this.opacity = source.opacity;
      this.transparent = source.transparent;
      this.blendSrc = source.blendSrc;
      this.blendDst = source.blendDst;
      this.blendEquation = source.blendEquation;
      this.blendSrcAlpha = source.blendSrcAlpha;
      this.blendDstAlpha = source.blendDstAlpha;
      this.blendEquationAlpha = source.blendEquationAlpha;
      this.depthFunc = source.depthFunc;
      this.depthTest = source.depthTest;
      this.depthWrite = source.depthWrite;
      this.colorWrite = source.colorWrite;
      this.precision = source.precision;
      this.polygonOffset = source.polygonOffset;
      this.polygonOffsetFactor = source.polygonOffsetFactor;
      this.polygonOffsetUnits = source.polygonOffsetUnits;
      this.alphaTest = source.alphaTest;
      this.premultipliedAlpha = source.premultipliedAlpha;
      this.overdraw = source.overdraw;
      this.visible = source.visible;
      this.clipShadows = source.clipShadows;
      var srcPlanes = source.clippingPlanes,
          dstPlanes = null;
      if (srcPlanes !== null) {
        var n = srcPlanes.length;
        dstPlanes = new Array(n);
        for (var i = 0; i !== n; ++i)
          dstPlanes[i] = srcPlanes[i].clone();
      }
      this.clippingPlanes = dstPlanes;
      return this;
    },
    update: function() {
      this.dispatchEvent({type: 'update'});
    },
    dispose: function() {
      this.dispatchEvent({type: 'dispose'});
    }
  };
  Object.assign(THREE.Material.prototype, THREE.EventDispatcher.prototype);
  THREE.MaterialIdCount = 0;
  THREE.LineBasicMaterial = function(parameters) {
    THREE.Material.call(this);
    this.type = 'LineBasicMaterial';
    this.color = new THREE.Color(0xffffff);
    this.linewidth = 1;
    this.linecap = 'round';
    this.linejoin = 'round';
    this.lights = false;
    this.setValues(parameters);
  };
  THREE.LineBasicMaterial.prototype = Object.create(THREE.Material.prototype);
  THREE.LineBasicMaterial.prototype.constructor = THREE.LineBasicMaterial;
  THREE.LineBasicMaterial.prototype.copy = function(source) {
    THREE.Material.prototype.copy.call(this, source);
    this.color.copy(source.color);
    this.linewidth = source.linewidth;
    this.linecap = source.linecap;
    this.linejoin = source.linejoin;
    return this;
  };
  THREE.LineDashedMaterial = function(parameters) {
    THREE.Material.call(this);
    this.type = 'LineDashedMaterial';
    this.color = new THREE.Color(0xffffff);
    this.linewidth = 1;
    this.scale = 1;
    this.dashSize = 3;
    this.gapSize = 1;
    this.lights = false;
    this.setValues(parameters);
  };
  THREE.LineDashedMaterial.prototype = Object.create(THREE.Material.prototype);
  THREE.LineDashedMaterial.prototype.constructor = THREE.LineDashedMaterial;
  THREE.LineDashedMaterial.prototype.copy = function(source) {
    THREE.Material.prototype.copy.call(this, source);
    this.color.copy(source.color);
    this.linewidth = source.linewidth;
    this.scale = source.scale;
    this.dashSize = source.dashSize;
    this.gapSize = source.gapSize;
    return this;
  };
  THREE.MeshBasicMaterial = function(parameters) {
    THREE.Material.call(this);
    this.type = 'MeshBasicMaterial';
    this.color = new THREE.Color(0xffffff);
    this.map = null;
    this.aoMap = null;
    this.aoMapIntensity = 1.0;
    this.specularMap = null;
    this.alphaMap = null;
    this.envMap = null;
    this.combine = THREE.MultiplyOperation;
    this.reflectivity = 1;
    this.refractionRatio = 0.98;
    this.wireframe = false;
    this.wireframeLinewidth = 1;
    this.wireframeLinecap = 'round';
    this.wireframeLinejoin = 'round';
    this.skinning = false;
    this.morphTargets = false;
    this.lights = false;
    this.setValues(parameters);
  };
  THREE.MeshBasicMaterial.prototype = Object.create(THREE.Material.prototype);
  THREE.MeshBasicMaterial.prototype.constructor = THREE.MeshBasicMaterial;
  THREE.MeshBasicMaterial.prototype.copy = function(source) {
    THREE.Material.prototype.copy.call(this, source);
    this.color.copy(source.color);
    this.map = source.map;
    this.aoMap = source.aoMap;
    this.aoMapIntensity = source.aoMapIntensity;
    this.specularMap = source.specularMap;
    this.alphaMap = source.alphaMap;
    this.envMap = source.envMap;
    this.combine = source.combine;
    this.reflectivity = source.reflectivity;
    this.refractionRatio = source.refractionRatio;
    this.wireframe = source.wireframe;
    this.wireframeLinewidth = source.wireframeLinewidth;
    this.wireframeLinecap = source.wireframeLinecap;
    this.wireframeLinejoin = source.wireframeLinejoin;
    this.skinning = source.skinning;
    this.morphTargets = source.morphTargets;
    return this;
  };
  THREE.MeshDepthMaterial = function(parameters) {
    THREE.Material.call(this);
    this.type = 'MeshDepthMaterial';
    this.depthPacking = THREE.BasicDepthPacking;
    this.skinning = false;
    this.morphTargets = false;
    this.map = null;
    this.alphaMap = null;
    this.displacementMap = null;
    this.displacementScale = 1;
    this.displacementBias = 0;
    this.wireframe = false;
    this.wireframeLinewidth = 1;
    this.fog = false;
    this.lights = false;
    this.setValues(parameters);
  };
  THREE.MeshDepthMaterial.prototype = Object.create(THREE.Material.prototype);
  THREE.MeshDepthMaterial.prototype.constructor = THREE.MeshDepthMaterial;
  THREE.MeshDepthMaterial.prototype.copy = function(source) {
    THREE.Material.prototype.copy.call(this, source);
    this.depthPacking = source.depthPacking;
    this.skinning = source.skinning;
    this.morphTargets = source.morphTargets;
    this.map = source.map;
    this.alphaMap = source.alphaMap;
    this.displacementMap = source.displacementMap;
    this.displacementScale = source.displacementScale;
    this.displacementBias = source.displacementBias;
    this.wireframe = source.wireframe;
    this.wireframeLinewidth = source.wireframeLinewidth;
    return this;
  };
  THREE.MeshLambertMaterial = function(parameters) {
    THREE.Material.call(this);
    this.type = 'MeshLambertMaterial';
    this.color = new THREE.Color(0xffffff);
    this.map = null;
    this.lightMap = null;
    this.lightMapIntensity = 1.0;
    this.aoMap = null;
    this.aoMapIntensity = 1.0;
    this.emissive = new THREE.Color(0x000000);
    this.emissiveIntensity = 1.0;
    this.emissiveMap = null;
    this.specularMap = null;
    this.alphaMap = null;
    this.envMap = null;
    this.combine = THREE.MultiplyOperation;
    this.reflectivity = 1;
    this.refractionRatio = 0.98;
    this.wireframe = false;
    this.wireframeLinewidth = 1;
    this.wireframeLinecap = 'round';
    this.wireframeLinejoin = 'round';
    this.skinning = false;
    this.morphTargets = false;
    this.morphNormals = false;
    this.setValues(parameters);
  };
  THREE.MeshLambertMaterial.prototype = Object.create(THREE.Material.prototype);
  THREE.MeshLambertMaterial.prototype.constructor = THREE.MeshLambertMaterial;
  THREE.MeshLambertMaterial.prototype.copy = function(source) {
    THREE.Material.prototype.copy.call(this, source);
    this.color.copy(source.color);
    this.map = source.map;
    this.lightMap = source.lightMap;
    this.lightMapIntensity = source.lightMapIntensity;
    this.aoMap = source.aoMap;
    this.aoMapIntensity = source.aoMapIntensity;
    this.emissive.copy(source.emissive);
    this.emissiveMap = source.emissiveMap;
    this.emissiveIntensity = source.emissiveIntensity;
    this.specularMap = source.specularMap;
    this.alphaMap = source.alphaMap;
    this.envMap = source.envMap;
    this.combine = source.combine;
    this.reflectivity = source.reflectivity;
    this.refractionRatio = source.refractionRatio;
    this.wireframe = source.wireframe;
    this.wireframeLinewidth = source.wireframeLinewidth;
    this.wireframeLinecap = source.wireframeLinecap;
    this.wireframeLinejoin = source.wireframeLinejoin;
    this.skinning = source.skinning;
    this.morphTargets = source.morphTargets;
    this.morphNormals = source.morphNormals;
    return this;
  };
  THREE.MeshNormalMaterial = function(parameters) {
    THREE.Material.call(this, parameters);
    this.type = 'MeshNormalMaterial';
    this.wireframe = false;
    this.wireframeLinewidth = 1;
    this.fog = false;
    this.lights = false;
    this.morphTargets = false;
    this.setValues(parameters);
  };
  THREE.MeshNormalMaterial.prototype = Object.create(THREE.Material.prototype);
  THREE.MeshNormalMaterial.prototype.constructor = THREE.MeshNormalMaterial;
  THREE.MeshNormalMaterial.prototype.copy = function(source) {
    THREE.Material.prototype.copy.call(this, source);
    this.wireframe = source.wireframe;
    this.wireframeLinewidth = source.wireframeLinewidth;
    return this;
  };
  THREE.MeshPhongMaterial = function(parameters) {
    THREE.Material.call(this);
    this.type = 'MeshPhongMaterial';
    this.color = new THREE.Color(0xffffff);
    this.specular = new THREE.Color(0x111111);
    this.shininess = 30;
    this.map = null;
    this.lightMap = null;
    this.lightMapIntensity = 1.0;
    this.aoMap = null;
    this.aoMapIntensity = 1.0;
    this.emissive = new THREE.Color(0x000000);
    this.emissiveIntensity = 1.0;
    this.emissiveMap = null;
    this.bumpMap = null;
    this.bumpScale = 1;
    this.normalMap = null;
    this.normalScale = new THREE.Vector2(1, 1);
    this.displacementMap = null;
    this.displacementScale = 1;
    this.displacementBias = 0;
    this.specularMap = null;
    this.alphaMap = null;
    this.envMap = null;
    this.combine = THREE.MultiplyOperation;
    this.reflectivity = 1;
    this.refractionRatio = 0.98;
    this.wireframe = false;
    this.wireframeLinewidth = 1;
    this.wireframeLinecap = 'round';
    this.wireframeLinejoin = 'round';
    this.skinning = false;
    this.morphTargets = false;
    this.morphNormals = false;
    this.setValues(parameters);
  };
  THREE.MeshPhongMaterial.prototype = Object.create(THREE.Material.prototype);
  THREE.MeshPhongMaterial.prototype.constructor = THREE.MeshPhongMaterial;
  THREE.MeshPhongMaterial.prototype.copy = function(source) {
    THREE.Material.prototype.copy.call(this, source);
    this.color.copy(source.color);
    this.specular.copy(source.specular);
    this.shininess = source.shininess;
    this.map = source.map;
    this.lightMap = source.lightMap;
    this.lightMapIntensity = source.lightMapIntensity;
    this.aoMap = source.aoMap;
    this.aoMapIntensity = source.aoMapIntensity;
    this.emissive.copy(source.emissive);
    this.emissiveMap = source.emissiveMap;
    this.emissiveIntensity = source.emissiveIntensity;
    this.bumpMap = source.bumpMap;
    this.bumpScale = source.bumpScale;
    this.normalMap = source.normalMap;
    this.normalScale.copy(source.normalScale);
    this.displacementMap = source.displacementMap;
    this.displacementScale = source.displacementScale;
    this.displacementBias = source.displacementBias;
    this.specularMap = source.specularMap;
    this.alphaMap = source.alphaMap;
    this.envMap = source.envMap;
    this.combine = source.combine;
    this.reflectivity = source.reflectivity;
    this.refractionRatio = source.refractionRatio;
    this.wireframe = source.wireframe;
    this.wireframeLinewidth = source.wireframeLinewidth;
    this.wireframeLinecap = source.wireframeLinecap;
    this.wireframeLinejoin = source.wireframeLinejoin;
    this.skinning = source.skinning;
    this.morphTargets = source.morphTargets;
    this.morphNormals = source.morphNormals;
    return this;
  };
  THREE.MeshStandardMaterial = function(parameters) {
    THREE.Material.call(this);
    this.defines = {'STANDARD': ''};
    this.type = 'MeshStandardMaterial';
    this.color = new THREE.Color(0xffffff);
    this.roughness = 0.5;
    this.metalness = 0.5;
    this.map = null;
    this.lightMap = null;
    this.lightMapIntensity = 1.0;
    this.aoMap = null;
    this.aoMapIntensity = 1.0;
    this.emissive = new THREE.Color(0x000000);
    this.emissiveIntensity = 1.0;
    this.emissiveMap = null;
    this.bumpMap = null;
    this.bumpScale = 1;
    this.normalMap = null;
    this.normalScale = new THREE.Vector2(1, 1);
    this.displacementMap = null;
    this.displacementScale = 1;
    this.displacementBias = 0;
    this.roughnessMap = null;
    this.metalnessMap = null;
    this.alphaMap = null;
    this.envMap = null;
    this.envMapIntensity = 1.0;
    this.refractionRatio = 0.98;
    this.wireframe = false;
    this.wireframeLinewidth = 1;
    this.wireframeLinecap = 'round';
    this.wireframeLinejoin = 'round';
    this.skinning = false;
    this.morphTargets = false;
    this.morphNormals = false;
    this.setValues(parameters);
  };
  THREE.MeshStandardMaterial.prototype = Object.create(THREE.Material.prototype);
  THREE.MeshStandardMaterial.prototype.constructor = THREE.MeshStandardMaterial;
  THREE.MeshStandardMaterial.prototype.copy = function(source) {
    THREE.Material.prototype.copy.call(this, source);
    this.defines = {'STANDARD': ''};
    this.color.copy(source.color);
    this.roughness = source.roughness;
    this.metalness = source.metalness;
    this.map = source.map;
    this.lightMap = source.lightMap;
    this.lightMapIntensity = source.lightMapIntensity;
    this.aoMap = source.aoMap;
    this.aoMapIntensity = source.aoMapIntensity;
    this.emissive.copy(source.emissive);
    this.emissiveMap = source.emissiveMap;
    this.emissiveIntensity = source.emissiveIntensity;
    this.bumpMap = source.bumpMap;
    this.bumpScale = source.bumpScale;
    this.normalMap = source.normalMap;
    this.normalScale.copy(source.normalScale);
    this.displacementMap = source.displacementMap;
    this.displacementScale = source.displacementScale;
    this.displacementBias = source.displacementBias;
    this.roughnessMap = source.roughnessMap;
    this.metalnessMap = source.metalnessMap;
    this.alphaMap = source.alphaMap;
    this.envMap = source.envMap;
    this.envMapIntensity = source.envMapIntensity;
    this.refractionRatio = source.refractionRatio;
    this.wireframe = source.wireframe;
    this.wireframeLinewidth = source.wireframeLinewidth;
    this.wireframeLinecap = source.wireframeLinecap;
    this.wireframeLinejoin = source.wireframeLinejoin;
    this.skinning = source.skinning;
    this.morphTargets = source.morphTargets;
    this.morphNormals = source.morphNormals;
    return this;
  };
  THREE.MeshPhysicalMaterial = function(parameters) {
    THREE.MeshStandardMaterial.call(this);
    this.defines = {'PHYSICAL': ''};
    this.type = 'MeshPhysicalMaterial';
    this.reflectivity = 0.5;
    this.clearCoat = 0.0;
    this.clearCoatRoughness = 0.0;
    this.setValues(parameters);
  };
  THREE.MeshPhysicalMaterial.prototype = Object.create(THREE.MeshStandardMaterial.prototype);
  THREE.MeshPhysicalMaterial.prototype.constructor = THREE.MeshPhysicalMaterial;
  THREE.MeshPhysicalMaterial.prototype.copy = function(source) {
    THREE.MeshStandardMaterial.prototype.copy.call(this, source);
    this.defines = {'PHYSICAL': ''};
    this.reflectivity = source.reflectivity;
    this.clearCoat = source.clearCoat;
    this.clearCoatRoughness = source.clearCoatRoughness;
    return this;
  };
  THREE.MultiMaterial = function(materials) {
    this.uuid = THREE.Math.generateUUID();
    this.type = 'MultiMaterial';
    this.materials = materials instanceof Array ? materials : [];
    this.visible = true;
  };
  THREE.MultiMaterial.prototype = {
    constructor: THREE.MultiMaterial,
    toJSON: function(meta) {
      var output = {
        metadata: {
          version: 4.2,
          type: 'material',
          generator: 'MaterialExporter'
        },
        uuid: this.uuid,
        type: this.type,
        materials: []
      };
      var materials = this.materials;
      for (var i = 0,
          l = materials.length; i < l; i++) {
        var material = materials[i].toJSON(meta);
        delete material.metadata;
        output.materials.push(material);
      }
      output.visible = this.visible;
      return output;
    },
    clone: function() {
      var material = new this.constructor();
      for (var i = 0; i < this.materials.length; i++) {
        material.materials.push(this.materials[i].clone());
      }
      material.visible = this.visible;
      return material;
    }
  };
  THREE.PointsMaterial = function(parameters) {
    THREE.Material.call(this);
    this.type = 'PointsMaterial';
    this.color = new THREE.Color(0xffffff);
    this.map = null;
    this.size = 1;
    this.sizeAttenuation = true;
    this.lights = false;
    this.setValues(parameters);
  };
  THREE.PointsMaterial.prototype = Object.create(THREE.Material.prototype);
  THREE.PointsMaterial.prototype.constructor = THREE.PointsMaterial;
  THREE.PointsMaterial.prototype.copy = function(source) {
    THREE.Material.prototype.copy.call(this, source);
    this.color.copy(source.color);
    this.map = source.map;
    this.size = source.size;
    this.sizeAttenuation = source.sizeAttenuation;
    return this;
  };
  THREE.ShaderMaterial = function(parameters) {
    THREE.Material.call(this);
    this.type = 'ShaderMaterial';
    this.defines = {};
    this.uniforms = {};
    this.vertexShader = 'void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}';
    this.fragmentShader = 'void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}';
    this.linewidth = 1;
    this.wireframe = false;
    this.wireframeLinewidth = 1;
    this.fog = false;
    this.lights = false;
    this.clipping = false;
    this.skinning = false;
    this.morphTargets = false;
    this.morphNormals = false;
    this.extensions = {
      derivatives: false,
      fragDepth: false,
      drawBuffers: false,
      shaderTextureLOD: false
    };
    this.defaultAttributeValues = {
      'color': [1, 1, 1],
      'uv': [0, 0],
      'uv2': [0, 0]
    };
    this.index0AttributeName = undefined;
    if (parameters !== undefined) {
      if (parameters.attributes !== undefined) {
        console.error('THREE.ShaderMaterial: attributes should now be defined in THREE.BufferGeometry instead.');
      }
      this.setValues(parameters);
    }
  };
  THREE.ShaderMaterial.prototype = Object.create(THREE.Material.prototype);
  THREE.ShaderMaterial.prototype.constructor = THREE.ShaderMaterial;
  THREE.ShaderMaterial.prototype.copy = function(source) {
    THREE.Material.prototype.copy.call(this, source);
    this.fragmentShader = source.fragmentShader;
    this.vertexShader = source.vertexShader;
    this.uniforms = THREE.UniformsUtils.clone(source.uniforms);
    this.defines = source.defines;
    this.wireframe = source.wireframe;
    this.wireframeLinewidth = source.wireframeLinewidth;
    this.lights = source.lights;
    this.clipping = source.clipping;
    this.skinning = source.skinning;
    this.morphTargets = source.morphTargets;
    this.morphNormals = source.morphNormals;
    this.extensions = source.extensions;
    return this;
  };
  THREE.ShaderMaterial.prototype.toJSON = function(meta) {
    var data = THREE.Material.prototype.toJSON.call(this, meta);
    data.uniforms = this.uniforms;
    data.vertexShader = this.vertexShader;
    data.fragmentShader = this.fragmentShader;
    return data;
  };
  THREE.RawShaderMaterial = function(parameters) {
    THREE.ShaderMaterial.call(this, parameters);
    this.type = 'RawShaderMaterial';
  };
  THREE.RawShaderMaterial.prototype = Object.create(THREE.ShaderMaterial.prototype);
  THREE.RawShaderMaterial.prototype.constructor = THREE.RawShaderMaterial;
  THREE.SpriteMaterial = function(parameters) {
    THREE.Material.call(this);
    this.type = 'SpriteMaterial';
    this.color = new THREE.Color(0xffffff);
    this.map = null;
    this.rotation = 0;
    this.fog = false;
    this.lights = false;
    this.setValues(parameters);
  };
  THREE.SpriteMaterial.prototype = Object.create(THREE.Material.prototype);
  THREE.SpriteMaterial.prototype.constructor = THREE.SpriteMaterial;
  THREE.SpriteMaterial.prototype.copy = function(source) {
    THREE.Material.prototype.copy.call(this, source);
    this.color.copy(source.color);
    this.map = source.map;
    this.rotation = source.rotation;
    return this;
  };
  THREE.ShadowMaterial = function() {
    THREE.ShaderMaterial.call(this, {
      uniforms: THREE.UniformsUtils.merge([THREE.UniformsLib["lights"], {opacity: {value: 1.0}}]),
      vertexShader: THREE.ShaderChunk['shadow_vert'],
      fragmentShader: THREE.ShaderChunk['shadow_frag']
    });
    this.lights = true;
    this.transparent = true;
    Object.defineProperties(this, {opacity: {
        enumerable: true,
        get: function() {
          return this.uniforms.opacity.value;
        },
        set: function(value) {
          this.uniforms.opacity.value = value;
        }
      }});
  };
  THREE.ShadowMaterial.prototype = Object.create(THREE.ShaderMaterial.prototype);
  THREE.ShadowMaterial.prototype.constructor = THREE.ShadowMaterial;
  THREE.Texture = function(image, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding) {
    Object.defineProperty(this, 'id', {value: THREE.TextureIdCount++});
    this.uuid = THREE.Math.generateUUID();
    this.name = '';
    this.sourceFile = '';
    this.image = image !== undefined ? image : THREE.Texture.DEFAULT_IMAGE;
    this.mipmaps = [];
    this.mapping = mapping !== undefined ? mapping : THREE.Texture.DEFAULT_MAPPING;
    this.wrapS = wrapS !== undefined ? wrapS : THREE.ClampToEdgeWrapping;
    this.wrapT = wrapT !== undefined ? wrapT : THREE.ClampToEdgeWrapping;
    this.magFilter = magFilter !== undefined ? magFilter : THREE.LinearFilter;
    this.minFilter = minFilter !== undefined ? minFilter : THREE.LinearMipMapLinearFilter;
    this.anisotropy = anisotropy !== undefined ? anisotropy : 1;
    this.format = format !== undefined ? format : THREE.RGBAFormat;
    this.type = type !== undefined ? type : THREE.UnsignedByteType;
    this.offset = new THREE.Vector2(0, 0);
    this.repeat = new THREE.Vector2(1, 1);
    this.generateMipmaps = true;
    this.premultiplyAlpha = false;
    this.flipY = true;
    this.unpackAlignment = 4;
    this.encoding = encoding !== undefined ? encoding : THREE.LinearEncoding;
    this.version = 0;
    this.onUpdate = null;
  };
  THREE.Texture.DEFAULT_IMAGE = undefined;
  THREE.Texture.DEFAULT_MAPPING = THREE.UVMapping;
  THREE.Texture.prototype = {
    constructor: THREE.Texture,
    set needsUpdate(value) {
      if (value === true)
        this.version++;
    },
    clone: function() {
      return new this.constructor().copy(this);
    },
    copy: function(source) {
      this.image = source.image;
      this.mipmaps = source.mipmaps.slice(0);
      this.mapping = source.mapping;
      this.wrapS = source.wrapS;
      this.wrapT = source.wrapT;
      this.magFilter = source.magFilter;
      this.minFilter = source.minFilter;
      this.anisotropy = source.anisotropy;
      this.format = source.format;
      this.type = source.type;
      this.offset.copy(source.offset);
      this.repeat.copy(source.repeat);
      this.generateMipmaps = source.generateMipmaps;
      this.premultiplyAlpha = source.premultiplyAlpha;
      this.flipY = source.flipY;
      this.unpackAlignment = source.unpackAlignment;
      this.encoding = source.encoding;
      return this;
    },
    toJSON: function(meta) {
      if (meta.textures[this.uuid] !== undefined) {
        return meta.textures[this.uuid];
      }
      function getDataURL(image) {
        var canvas;
        if (image.toDataURL !== undefined) {
          canvas = image;
        } else {
          canvas = document.createElementNS('http://www.w3.org/1999/xhtml', 'canvas');
          canvas.width = image.width;
          canvas.height = image.height;
          canvas.getContext('2d').drawImage(image, 0, 0, image.width, image.height);
        }
        if (canvas.width > 2048 || canvas.height > 2048) {
          return canvas.toDataURL('image/jpeg', 0.6);
        } else {
          return canvas.toDataURL('image/png');
        }
      }
      var output = {
        metadata: {
          version: 4.4,
          type: 'Texture',
          generator: 'Texture.toJSON'
        },
        uuid: this.uuid,
        name: this.name,
        mapping: this.mapping,
        repeat: [this.repeat.x, this.repeat.y],
        offset: [this.offset.x, this.offset.y],
        wrap: [this.wrapS, this.wrapT],
        minFilter: this.minFilter,
        magFilter: this.magFilter,
        anisotropy: this.anisotropy
      };
      if (this.image !== undefined) {
        var image = this.image;
        if (image.uuid === undefined) {
          image.uuid = THREE.Math.generateUUID();
        }
        if (meta.images[image.uuid] === undefined) {
          meta.images[image.uuid] = {
            uuid: image.uuid,
            url: getDataURL(image)
          };
        }
        output.image = image.uuid;
      }
      meta.textures[this.uuid] = output;
      return output;
    },
    dispose: function() {
      this.dispatchEvent({type: 'dispose'});
    },
    transformUv: function(uv) {
      if (this.mapping !== THREE.UVMapping)
        return;
      uv.multiply(this.repeat);
      uv.add(this.offset);
      if (uv.x < 0 || uv.x > 1) {
        switch (this.wrapS) {
          case THREE.RepeatWrapping:
            uv.x = uv.x - Math.floor(uv.x);
            break;
          case THREE.ClampToEdgeWrapping:
            uv.x = uv.x < 0 ? 0 : 1;
            break;
          case THREE.MirroredRepeatWrapping:
            if (Math.abs(Math.floor(uv.x) % 2) === 1) {
              uv.x = Math.ceil(uv.x) - uv.x;
            } else {
              uv.x = uv.x - Math.floor(uv.x);
            }
            break;
        }
      }
      if (uv.y < 0 || uv.y > 1) {
        switch (this.wrapT) {
          case THREE.RepeatWrapping:
            uv.y = uv.y - Math.floor(uv.y);
            break;
          case THREE.ClampToEdgeWrapping:
            uv.y = uv.y < 0 ? 0 : 1;
            break;
          case THREE.MirroredRepeatWrapping:
            if (Math.abs(Math.floor(uv.y) % 2) === 1) {
              uv.y = Math.ceil(uv.y) - uv.y;
            } else {
              uv.y = uv.y - Math.floor(uv.y);
            }
            break;
        }
      }
      if (this.flipY) {
        uv.y = 1 - uv.y;
      }
    }
  };
  Object.assign(THREE.Texture.prototype, THREE.EventDispatcher.prototype);
  THREE.TextureIdCount = 0;
  THREE.DepthTexture = function(width, height, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy) {
    THREE.Texture.call(this, null, mapping, wrapS, wrapT, magFilter, minFilter, THREE.DepthFormat, type, anisotropy);
    this.image = {
      width: width,
      height: height
    };
    this.type = type !== undefined ? type : THREE.UnsignedShortType;
    this.magFilter = magFilter !== undefined ? magFilter : THREE.NearestFilter;
    this.minFilter = minFilter !== undefined ? minFilter : THREE.NearestFilter;
    this.flipY = false;
    this.generateMipmaps = false;
  };
  THREE.DepthTexture.prototype = Object.create(THREE.Texture.prototype);
  THREE.DepthTexture.prototype.constructor = THREE.DepthTexture;
  THREE.CanvasTexture = function(canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy) {
    THREE.Texture.call(this, canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy);
    this.needsUpdate = true;
  };
  THREE.CanvasTexture.prototype = Object.create(THREE.Texture.prototype);
  THREE.CanvasTexture.prototype.constructor = THREE.CanvasTexture;
  THREE.CubeTexture = function(images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding) {
    images = images !== undefined ? images : [];
    mapping = mapping !== undefined ? mapping : THREE.CubeReflectionMapping;
    THREE.Texture.call(this, images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding);
    this.flipY = false;
  };
  THREE.CubeTexture.prototype = Object.create(THREE.Texture.prototype);
  THREE.CubeTexture.prototype.constructor = THREE.CubeTexture;
  Object.defineProperty(THREE.CubeTexture.prototype, 'images', {
    get: function() {
      return this.image;
    },
    set: function(value) {
      this.image = value;
    }
  });
  THREE.CompressedTexture = function(mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding) {
    THREE.Texture.call(this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding);
    this.image = {
      width: width,
      height: height
    };
    this.mipmaps = mipmaps;
    this.flipY = false;
    this.generateMipmaps = false;
  };
  THREE.CompressedTexture.prototype = Object.create(THREE.Texture.prototype);
  THREE.CompressedTexture.prototype.constructor = THREE.CompressedTexture;
  THREE.DataTexture = function(data, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding) {
    THREE.Texture.call(this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding);
    this.image = {
      data: data,
      width: width,
      height: height
    };
    this.magFilter = magFilter !== undefined ? magFilter : THREE.NearestFilter;
    this.minFilter = minFilter !== undefined ? minFilter : THREE.NearestFilter;
    this.flipY = false;
    this.generateMipmaps = false;
  };
  THREE.DataTexture.prototype = Object.create(THREE.Texture.prototype);
  THREE.DataTexture.prototype.constructor = THREE.DataTexture;
  THREE.VideoTexture = function(video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy) {
    THREE.Texture.call(this, video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy);
    this.generateMipmaps = false;
    var scope = this;
    function update() {
      requestAnimationFrame(update);
      if (video.readyState >= video.HAVE_CURRENT_DATA) {
        scope.needsUpdate = true;
      }
    }
    update();
  };
  THREE.VideoTexture.prototype = Object.create(THREE.Texture.prototype);
  THREE.VideoTexture.prototype.constructor = THREE.VideoTexture;
  THREE.Group = function() {
    THREE.Object3D.call(this);
    this.type = 'Group';
  };
  THREE.Group.prototype = Object.assign(Object.create(THREE.Object3D.prototype), {constructor: THREE.Group});
  THREE.Points = function(geometry, material) {
    THREE.Object3D.call(this);
    this.type = 'Points';
    this.geometry = geometry !== undefined ? geometry : new THREE.BufferGeometry();
    this.material = material !== undefined ? material : new THREE.PointsMaterial({color: Math.random() * 0xffffff});
  };
  THREE.Points.prototype = Object.assign(Object.create(THREE.Object3D.prototype), {
    constructor: THREE.Points,
    raycast: (function() {
      var inverseMatrix = new THREE.Matrix4();
      var ray = new THREE.Ray();
      var sphere = new THREE.Sphere();
      return function raycast(raycaster, intersects) {
        var object = this;
        var geometry = this.geometry;
        var matrixWorld = this.matrixWorld;
        var threshold = raycaster.params.Points.threshold;
        if (geometry.boundingSphere === null)
          geometry.computeBoundingSphere();
        sphere.copy(geometry.boundingSphere);
        sphere.applyMatrix4(matrixWorld);
        if (raycaster.ray.intersectsSphere(sphere) === false)
          return;
        inverseMatrix.getInverse(matrixWorld);
        ray.copy(raycaster.ray).applyMatrix4(inverseMatrix);
        var localThreshold = threshold / ((this.scale.x + this.scale.y + this.scale.z) / 3);
        var localThresholdSq = localThreshold * localThreshold;
        var position = new THREE.Vector3();
        function testPoint(point, index) {
          var rayPointDistanceSq = ray.distanceSqToPoint(point);
          if (rayPointDistanceSq < localThresholdSq) {
            var intersectPoint = ray.closestPointToPoint(point);
            intersectPoint.applyMatrix4(matrixWorld);
            var distance = raycaster.ray.origin.distanceTo(intersectPoint);
            if (distance < raycaster.near || distance > raycaster.far)
              return;
            intersects.push({
              distance: distance,
              distanceToRay: Math.sqrt(rayPointDistanceSq),
              point: intersectPoint.clone(),
              index: index,
              face: null,
              object: object
            });
          }
        }
        if (geometry instanceof THREE.BufferGeometry) {
          var index = geometry.index;
          var attributes = geometry.attributes;
          var positions = attributes.position.array;
          if (index !== null) {
            var indices = index.array;
            for (var i = 0,
                il = indices.length; i < il; i++) {
              var a = indices[i];
              position.fromArray(positions, a * 3);
              testPoint(position, a);
            }
          } else {
            for (var i = 0,
                l = positions.length / 3; i < l; i++) {
              position.fromArray(positions, i * 3);
              testPoint(position, i);
            }
          }
        } else {
          var vertices = geometry.vertices;
          for (var i = 0,
              l = vertices.length; i < l; i++) {
            testPoint(vertices[i], i);
          }
        }
      };
    }()),
    clone: function() {
      return new this.constructor(this.geometry, this.material).copy(this);
    }
  });
  THREE.Line = function(geometry, material, mode) {
    if (mode === 1) {
      console.warn('THREE.Line: parameter THREE.LinePieces no longer supported. Created THREE.LineSegments instead.');
      return new THREE.LineSegments(geometry, material);
    }
    THREE.Object3D.call(this);
    this.type = 'Line';
    this.geometry = geometry !== undefined ? geometry : new THREE.BufferGeometry();
    this.material = material !== undefined ? material : new THREE.LineBasicMaterial({color: Math.random() * 0xffffff});
  };
  THREE.Line.prototype = Object.assign(Object.create(THREE.Object3D.prototype), {
    constructor: THREE.Line,
    raycast: (function() {
      var inverseMatrix = new THREE.Matrix4();
      var ray = new THREE.Ray();
      var sphere = new THREE.Sphere();
      return function raycast(raycaster, intersects) {
        var precision = raycaster.linePrecision;
        var precisionSq = precision * precision;
        var geometry = this.geometry;
        var matrixWorld = this.matrixWorld;
        if (geometry.boundingSphere === null)
          geometry.computeBoundingSphere();
        sphere.copy(geometry.boundingSphere);
        sphere.applyMatrix4(matrixWorld);
        if (raycaster.ray.intersectsSphere(sphere) === false)
          return;
        inverseMatrix.getInverse(matrixWorld);
        ray.copy(raycaster.ray).applyMatrix4(inverseMatrix);
        var vStart = new THREE.Vector3();
        var vEnd = new THREE.Vector3();
        var interSegment = new THREE.Vector3();
        var interRay = new THREE.Vector3();
        var step = this instanceof THREE.LineSegments ? 2 : 1;
        if (geometry instanceof THREE.BufferGeometry) {
          var index = geometry.index;
          var attributes = geometry.attributes;
          var positions = attributes.position.array;
          if (index !== null) {
            var indices = index.array;
            for (var i = 0,
                l = indices.length - 1; i < l; i += step) {
              var a = indices[i];
              var b = indices[i + 1];
              vStart.fromArray(positions, a * 3);
              vEnd.fromArray(positions, b * 3);
              var distSq = ray.distanceSqToSegment(vStart, vEnd, interRay, interSegment);
              if (distSq > precisionSq)
                continue;
              interRay.applyMatrix4(this.matrixWorld);
              var distance = raycaster.ray.origin.distanceTo(interRay);
              if (distance < raycaster.near || distance > raycaster.far)
                continue;
              intersects.push({
                distance: distance,
                point: interSegment.clone().applyMatrix4(this.matrixWorld),
                index: i,
                face: null,
                faceIndex: null,
                object: this
              });
            }
          } else {
            for (var i = 0,
                l = positions.length / 3 - 1; i < l; i += step) {
              vStart.fromArray(positions, 3 * i);
              vEnd.fromArray(positions, 3 * i + 3);
              var distSq = ray.distanceSqToSegment(vStart, vEnd, interRay, interSegment);
              if (distSq > precisionSq)
                continue;
              interRay.applyMatrix4(this.matrixWorld);
              var distance = raycaster.ray.origin.distanceTo(interRay);
              if (distance < raycaster.near || distance > raycaster.far)
                continue;
              intersects.push({
                distance: distance,
                point: interSegment.clone().applyMatrix4(this.matrixWorld),
                index: i,
                face: null,
                faceIndex: null,
                object: this
              });
            }
          }
        } else if (geometry instanceof THREE.Geometry) {
          var vertices = geometry.vertices;
          var nbVertices = vertices.length;
          for (var i = 0; i < nbVertices - 1; i += step) {
            var distSq = ray.distanceSqToSegment(vertices[i], vertices[i + 1], interRay, interSegment);
            if (distSq > precisionSq)
              continue;
            interRay.applyMatrix4(this.matrixWorld);
            var distance = raycaster.ray.origin.distanceTo(interRay);
            if (distance < raycaster.near || distance > raycaster.far)
              continue;
            intersects.push({
              distance: distance,
              point: interSegment.clone().applyMatrix4(this.matrixWorld),
              index: i,
              face: null,
              faceIndex: null,
              object: this
            });
          }
        }
      };
    }()),
    clone: function() {
      return new this.constructor(this.geometry, this.material).copy(this);
    }
  });
  THREE.LineSegments = function(geometry, material) {
    THREE.Line.call(this, geometry, material);
    this.type = 'LineSegments';
  };
  THREE.LineSegments.prototype = Object.assign(Object.create(THREE.Line.prototype), {constructor: THREE.LineSegments});
  THREE.Mesh = function(geometry, material) {
    THREE.Object3D.call(this);
    this.type = 'Mesh';
    this.geometry = geometry !== undefined ? geometry : new THREE.BufferGeometry();
    this.material = material !== undefined ? material : new THREE.MeshBasicMaterial({color: Math.random() * 0xffffff});
    this.drawMode = THREE.TrianglesDrawMode;
    this.updateMorphTargets();
  };
  THREE.Mesh.prototype = Object.assign(Object.create(THREE.Object3D.prototype), {
    constructor: THREE.Mesh,
    setDrawMode: function(value) {
      this.drawMode = value;
    },
    copy: function(source) {
      THREE.Object3D.prototype.copy.call(this, source);
      this.drawMode = source.drawMode;
      return this;
    },
    updateMorphTargets: function() {
      if (this.geometry.morphTargets !== undefined && this.geometry.morphTargets.length > 0) {
        this.morphTargetBase = -1;
        this.morphTargetInfluences = [];
        this.morphTargetDictionary = {};
        for (var m = 0,
            ml = this.geometry.morphTargets.length; m < ml; m++) {
          this.morphTargetInfluences.push(0);
          this.morphTargetDictionary[this.geometry.morphTargets[m].name] = m;
        }
      }
    },
    getMorphTargetIndexByName: function(name) {
      if (this.morphTargetDictionary[name] !== undefined) {
        return this.morphTargetDictionary[name];
      }
      console.warn('THREE.Mesh.getMorphTargetIndexByName: morph target ' + name + ' does not exist. Returning 0.');
      return 0;
    },
    raycast: (function() {
      var inverseMatrix = new THREE.Matrix4();
      var ray = new THREE.Ray();
      var sphere = new THREE.Sphere();
      var vA = new THREE.Vector3();
      var vB = new THREE.Vector3();
      var vC = new THREE.Vector3();
      var tempA = new THREE.Vector3();
      var tempB = new THREE.Vector3();
      var tempC = new THREE.Vector3();
      var uvA = new THREE.Vector2();
      var uvB = new THREE.Vector2();
      var uvC = new THREE.Vector2();
      var barycoord = new THREE.Vector3();
      var intersectionPoint = new THREE.Vector3();
      var intersectionPointWorld = new THREE.Vector3();
      function uvIntersection(point, p1, p2, p3, uv1, uv2, uv3) {
        THREE.Triangle.barycoordFromPoint(point, p1, p2, p3, barycoord);
        uv1.multiplyScalar(barycoord.x);
        uv2.multiplyScalar(barycoord.y);
        uv3.multiplyScalar(barycoord.z);
        uv1.add(uv2).add(uv3);
        return uv1.clone();
      }
      function checkIntersection(object, raycaster, ray, pA, pB, pC, point) {
        var intersect;
        var material = object.material;
        if (material.side === THREE.BackSide) {
          intersect = ray.intersectTriangle(pC, pB, pA, true, point);
        } else {
          intersect = ray.intersectTriangle(pA, pB, pC, material.side !== THREE.DoubleSide, point);
        }
        if (intersect === null)
          return null;
        intersectionPointWorld.copy(point);
        intersectionPointWorld.applyMatrix4(object.matrixWorld);
        var distance = raycaster.ray.origin.distanceTo(intersectionPointWorld);
        if (distance < raycaster.near || distance > raycaster.far)
          return null;
        return {
          distance: distance,
          point: intersectionPointWorld.clone(),
          object: object
        };
      }
      function checkBufferGeometryIntersection(object, raycaster, ray, positions, uvs, a, b, c) {
        vA.fromArray(positions, a * 3);
        vB.fromArray(positions, b * 3);
        vC.fromArray(positions, c * 3);
        var intersection = checkIntersection(object, raycaster, ray, vA, vB, vC, intersectionPoint);
        if (intersection) {
          if (uvs) {
            uvA.fromArray(uvs, a * 2);
            uvB.fromArray(uvs, b * 2);
            uvC.fromArray(uvs, c * 2);
            intersection.uv = uvIntersection(intersectionPoint, vA, vB, vC, uvA, uvB, uvC);
          }
          intersection.face = new THREE.Face3(a, b, c, THREE.Triangle.normal(vA, vB, vC));
          intersection.faceIndex = a;
        }
        return intersection;
      }
      return function raycast(raycaster, intersects) {
        var geometry = this.geometry;
        var material = this.material;
        var matrixWorld = this.matrixWorld;
        if (material === undefined)
          return;
        if (geometry.boundingSphere === null)
          geometry.computeBoundingSphere();
        sphere.copy(geometry.boundingSphere);
        sphere.applyMatrix4(matrixWorld);
        if (raycaster.ray.intersectsSphere(sphere) === false)
          return;
        inverseMatrix.getInverse(matrixWorld);
        ray.copy(raycaster.ray).applyMatrix4(inverseMatrix);
        if (geometry.boundingBox !== null) {
          if (ray.intersectsBox(geometry.boundingBox) === false)
            return;
        }
        var uvs,
            intersection;
        if (geometry instanceof THREE.BufferGeometry) {
          var a,
              b,
              c;
          var index = geometry.index;
          var attributes = geometry.attributes;
          var positions = attributes.position.array;
          if (attributes.uv !== undefined) {
            uvs = attributes.uv.array;
          }
          if (index !== null) {
            var indices = index.array;
            for (var i = 0,
                l = indices.length; i < l; i += 3) {
              a = indices[i];
              b = indices[i + 1];
              c = indices[i + 2];
              intersection = checkBufferGeometryIntersection(this, raycaster, ray, positions, uvs, a, b, c);
              if (intersection) {
                intersection.faceIndex = Math.floor(i / 3);
                intersects.push(intersection);
              }
            }
          } else {
            for (var i = 0,
                l = positions.length; i < l; i += 9) {
              a = i / 3;
              b = a + 1;
              c = a + 2;
              intersection = checkBufferGeometryIntersection(this, raycaster, ray, positions, uvs, a, b, c);
              if (intersection) {
                intersection.index = a;
                intersects.push(intersection);
              }
            }
          }
        } else if (geometry instanceof THREE.Geometry) {
          var fvA,
              fvB,
              fvC;
          var isFaceMaterial = material instanceof THREE.MultiMaterial;
          var materials = isFaceMaterial === true ? material.materials : null;
          var vertices = geometry.vertices;
          var faces = geometry.faces;
          var faceVertexUvs = geometry.faceVertexUvs[0];
          if (faceVertexUvs.length > 0)
            uvs = faceVertexUvs;
          for (var f = 0,
              fl = faces.length; f < fl; f++) {
            var face = faces[f];
            var faceMaterial = isFaceMaterial === true ? materials[face.materialIndex] : material;
            if (faceMaterial === undefined)
              continue;
            fvA = vertices[face.a];
            fvB = vertices[face.b];
            fvC = vertices[face.c];
            if (faceMaterial.morphTargets === true) {
              var morphTargets = geometry.morphTargets;
              var morphInfluences = this.morphTargetInfluences;
              vA.set(0, 0, 0);
              vB.set(0, 0, 0);
              vC.set(0, 0, 0);
              for (var t = 0,
                  tl = morphTargets.length; t < tl; t++) {
                var influence = morphInfluences[t];
                if (influence === 0)
                  continue;
                var targets = morphTargets[t].vertices;
                vA.addScaledVector(tempA.subVectors(targets[face.a], fvA), influence);
                vB.addScaledVector(tempB.subVectors(targets[face.b], fvB), influence);
                vC.addScaledVector(tempC.subVectors(targets[face.c], fvC), influence);
              }
              vA.add(fvA);
              vB.add(fvB);
              vC.add(fvC);
              fvA = vA;
              fvB = vB;
              fvC = vC;
            }
            intersection = checkIntersection(this, raycaster, ray, fvA, fvB, fvC, intersectionPoint);
            if (intersection) {
              if (uvs) {
                var uvs_f = uvs[f];
                uvA.copy(uvs_f[0]);
                uvB.copy(uvs_f[1]);
                uvC.copy(uvs_f[2]);
                intersection.uv = uvIntersection(intersectionPoint, fvA, fvB, fvC, uvA, uvB, uvC);
              }
              intersection.face = face;
              intersection.faceIndex = f;
              intersects.push(intersection);
            }
          }
        }
      };
    }()),
    clone: function() {
      return new this.constructor(this.geometry, this.material).copy(this);
    }
  });
  THREE.Bone = function(skin) {
    THREE.Object3D.call(this);
    this.type = 'Bone';
    this.skin = skin;
  };
  THREE.Bone.prototype = Object.assign(Object.create(THREE.Object3D.prototype), {
    constructor: THREE.Bone,
    copy: function(source) {
      THREE.Object3D.prototype.copy.call(this, source);
      this.skin = source.skin;
      return this;
    }
  });
  THREE.Skeleton = function(bones, boneInverses, useVertexTexture) {
    this.useVertexTexture = useVertexTexture !== undefined ? useVertexTexture : true;
    this.identityMatrix = new THREE.Matrix4();
    bones = bones || [];
    this.bones = bones.slice(0);
    if (this.useVertexTexture) {
      var size = Math.sqrt(this.bones.length * 4);
      size = THREE.Math.nextPowerOfTwo(Math.ceil(size));
      size = Math.max(size, 4);
      this.boneTextureWidth = size;
      this.boneTextureHeight = size;
      this.boneMatrices = new Float32Array(this.boneTextureWidth * this.boneTextureHeight * 4);
      this.boneTexture = new THREE.DataTexture(this.boneMatrices, this.boneTextureWidth, this.boneTextureHeight, THREE.RGBAFormat, THREE.FloatType);
    } else {
      this.boneMatrices = new Float32Array(16 * this.bones.length);
    }
    if (boneInverses === undefined) {
      this.calculateInverses();
    } else {
      if (this.bones.length === boneInverses.length) {
        this.boneInverses = boneInverses.slice(0);
      } else {
        console.warn('THREE.Skeleton bonInverses is the wrong length.');
        this.boneInverses = [];
        for (var b = 0,
            bl = this.bones.length; b < bl; b++) {
          this.boneInverses.push(new THREE.Matrix4());
        }
      }
    }
  };
  Object.assign(THREE.Skeleton.prototype, {
    calculateInverses: function() {
      this.boneInverses = [];
      for (var b = 0,
          bl = this.bones.length; b < bl; b++) {
        var inverse = new THREE.Matrix4();
        if (this.bones[b]) {
          inverse.getInverse(this.bones[b].matrixWorld);
        }
        this.boneInverses.push(inverse);
      }
    },
    pose: function() {
      var bone;
      for (var b = 0,
          bl = this.bones.length; b < bl; b++) {
        bone = this.bones[b];
        if (bone) {
          bone.matrixWorld.getInverse(this.boneInverses[b]);
        }
      }
      for (var b = 0,
          bl = this.bones.length; b < bl; b++) {
        bone = this.bones[b];
        if (bone) {
          if (bone.parent instanceof THREE.Bone) {
            bone.matrix.getInverse(bone.parent.matrixWorld);
            bone.matrix.multiply(bone.matrixWorld);
          } else {
            bone.matrix.copy(bone.matrixWorld);
          }
          bone.matrix.decompose(bone.position, bone.quaternion, bone.scale);
        }
      }
    },
    update: (function() {
      var offsetMatrix = new THREE.Matrix4();
      return function update() {
        for (var b = 0,
            bl = this.bones.length; b < bl; b++) {
          var matrix = this.bones[b] ? this.bones[b].matrixWorld : this.identityMatrix;
          offsetMatrix.multiplyMatrices(matrix, this.boneInverses[b]);
          offsetMatrix.toArray(this.boneMatrices, b * 16);
        }
        if (this.useVertexTexture) {
          this.boneTexture.needsUpdate = true;
        }
      };
    })(),
    clone: function() {
      return new THREE.Skeleton(this.bones, this.boneInverses, this.useVertexTexture);
    }
  });
  THREE.SkinnedMesh = function(geometry, material, useVertexTexture) {
    THREE.Mesh.call(this, geometry, material);
    this.type = 'SkinnedMesh';
    this.bindMode = "attached";
    this.bindMatrix = new THREE.Matrix4();
    this.bindMatrixInverse = new THREE.Matrix4();
    var bones = [];
    if (this.geometry && this.geometry.bones !== undefined) {
      var bone,
          gbone;
      for (var b = 0,
          bl = this.geometry.bones.length; b < bl; ++b) {
        gbone = this.geometry.bones[b];
        bone = new THREE.Bone(this);
        bones.push(bone);
        bone.name = gbone.name;
        bone.position.fromArray(gbone.pos);
        bone.quaternion.fromArray(gbone.rotq);
        if (gbone.scl !== undefined)
          bone.scale.fromArray(gbone.scl);
      }
      for (var b = 0,
          bl = this.geometry.bones.length; b < bl; ++b) {
        gbone = this.geometry.bones[b];
        if (gbone.parent !== -1 && gbone.parent !== null && bones[gbone.parent] !== undefined) {
          bones[gbone.parent].add(bones[b]);
        } else {
          this.add(bones[b]);
        }
      }
    }
    this.normalizeSkinWeights();
    this.updateMatrixWorld(true);
    this.bind(new THREE.Skeleton(bones, undefined, useVertexTexture), this.matrixWorld);
  };
  THREE.SkinnedMesh.prototype = Object.assign(Object.create(THREE.Mesh.prototype), {
    constructor: THREE.SkinnedMesh,
    bind: function(skeleton, bindMatrix) {
      this.skeleton = skeleton;
      if (bindMatrix === undefined) {
        this.updateMatrixWorld(true);
        this.skeleton.calculateInverses();
        bindMatrix = this.matrixWorld;
      }
      this.bindMatrix.copy(bindMatrix);
      this.bindMatrixInverse.getInverse(bindMatrix);
    },
    pose: function() {
      this.skeleton.pose();
    },
    normalizeSkinWeights: function() {
      if (this.geometry instanceof THREE.Geometry) {
        for (var i = 0; i < this.geometry.skinWeights.length; i++) {
          var sw = this.geometry.skinWeights[i];
          var scale = 1.0 / sw.lengthManhattan();
          if (scale !== Infinity) {
            sw.multiplyScalar(scale);
          } else {
            sw.set(1, 0, 0, 0);
          }
        }
      } else if (this.geometry instanceof THREE.BufferGeometry) {
        var vec = new THREE.Vector4();
        var skinWeight = this.geometry.attributes.skinWeight;
        for (var i = 0; i < skinWeight.count; i++) {
          vec.x = skinWeight.getX(i);
          vec.y = skinWeight.getY(i);
          vec.z = skinWeight.getZ(i);
          vec.w = skinWeight.getW(i);
          var scale = 1.0 / vec.lengthManhattan();
          if (scale !== Infinity) {
            vec.multiplyScalar(scale);
          } else {
            vec.set(1, 0, 0, 0);
          }
          skinWeight.setXYZW(i, vec.x, vec.y, vec.z, vec.w);
        }
      }
    },
    updateMatrixWorld: function(force) {
      THREE.Mesh.prototype.updateMatrixWorld.call(this, true);
      if (this.bindMode === "attached") {
        this.bindMatrixInverse.getInverse(this.matrixWorld);
      } else if (this.bindMode === "detached") {
        this.bindMatrixInverse.getInverse(this.bindMatrix);
      } else {
        console.warn('THREE.SkinnedMesh unrecognized bindMode: ' + this.bindMode);
      }
    },
    clone: function() {
      return new this.constructor(this.geometry, this.material, this.skeleton.useVertexTexture).copy(this);
    }
  });
  THREE.LOD = function() {
    THREE.Object3D.call(this);
    this.type = 'LOD';
    Object.defineProperties(this, {levels: {
        enumerable: true,
        value: []
      }});
  };
  THREE.LOD.prototype = Object.assign(Object.create(THREE.Object3D.prototype), {
    constructor: THREE.LOD,
    copy: function(source) {
      THREE.Object3D.prototype.copy.call(this, source, false);
      var levels = source.levels;
      for (var i = 0,
          l = levels.length; i < l; i++) {
        var level = levels[i];
        this.addLevel(level.object.clone(), level.distance);
      }
      return this;
    },
    addLevel: function(object, distance) {
      if (distance === undefined)
        distance = 0;
      distance = Math.abs(distance);
      var levels = this.levels;
      for (var l = 0; l < levels.length; l++) {
        if (distance < levels[l].distance) {
          break;
        }
      }
      levels.splice(l, 0, {
        distance: distance,
        object: object
      });
      this.add(object);
    },
    getObjectForDistance: function(distance) {
      var levels = this.levels;
      for (var i = 1,
          l = levels.length; i < l; i++) {
        if (distance < levels[i].distance) {
          break;
        }
      }
      return levels[i - 1].object;
    },
    raycast: (function() {
      var matrixPosition = new THREE.Vector3();
      return function raycast(raycaster, intersects) {
        matrixPosition.setFromMatrixPosition(this.matrixWorld);
        var distance = raycaster.ray.origin.distanceTo(matrixPosition);
        this.getObjectForDistance(distance).raycast(raycaster, intersects);
      };
    }()),
    update: function() {
      var v1 = new THREE.Vector3();
      var v2 = new THREE.Vector3();
      return function update(camera) {
        var levels = this.levels;
        if (levels.length > 1) {
          v1.setFromMatrixPosition(camera.matrixWorld);
          v2.setFromMatrixPosition(this.matrixWorld);
          var distance = v1.distanceTo(v2);
          levels[0].object.visible = true;
          for (var i = 1,
              l = levels.length; i < l; i++) {
            if (distance >= levels[i].distance) {
              levels[i - 1].object.visible = false;
              levels[i].object.visible = true;
            } else {
              break;
            }
          }
          for (; i < l; i++) {
            levels[i].object.visible = false;
          }
        }
      };
    }(),
    toJSON: function(meta) {
      var data = THREE.Object3D.prototype.toJSON.call(this, meta);
      data.object.levels = [];
      var levels = this.levels;
      for (var i = 0,
          l = levels.length; i < l; i++) {
        var level = levels[i];
        data.object.levels.push({
          object: level.object.uuid,
          distance: level.distance
        });
      }
      return data;
    }
  });
  THREE.Sprite = function(material) {
    THREE.Object3D.call(this);
    this.type = 'Sprite';
    this.material = (material !== undefined) ? material : new THREE.SpriteMaterial();
  };
  THREE.Sprite.prototype = Object.assign(Object.create(THREE.Object3D.prototype), {
    constructor: THREE.Sprite,
    raycast: (function() {
      var matrixPosition = new THREE.Vector3();
      return function raycast(raycaster, intersects) {
        matrixPosition.setFromMatrixPosition(this.matrixWorld);
        var distanceSq = raycaster.ray.distanceSqToPoint(matrixPosition);
        var guessSizeSq = this.scale.x * this.scale.y / 4;
        if (distanceSq > guessSizeSq) {
          return;
        }
        intersects.push({
          distance: Math.sqrt(distanceSq),
          point: this.position,
          face: null,
          object: this
        });
      };
    }()),
    clone: function() {
      return new this.constructor(this.material).copy(this);
    }
  });
  THREE.LensFlare = function(texture, size, distance, blending, color) {
    THREE.Object3D.call(this);
    this.lensFlares = [];
    this.positionScreen = new THREE.Vector3();
    this.customUpdateCallback = undefined;
    if (texture !== undefined) {
      this.add(texture, size, distance, blending, color);
    }
  };
  THREE.LensFlare.prototype = Object.assign(Object.create(THREE.Object3D.prototype), {
    constructor: THREE.LensFlare,
    copy: function(source) {
      THREE.Object3D.prototype.copy.call(this, source);
      this.positionScreen.copy(source.positionScreen);
      this.customUpdateCallback = source.customUpdateCallback;
      for (var i = 0,
          l = source.lensFlares.length; i < l; i++) {
        this.lensFlares.push(source.lensFlares[i]);
      }
      return this;
    },
    add: function(texture, size, distance, blending, color, opacity) {
      if (size === undefined)
        size = -1;
      if (distance === undefined)
        distance = 0;
      if (opacity === undefined)
        opacity = 1;
      if (color === undefined)
        color = new THREE.Color(0xffffff);
      if (blending === undefined)
        blending = THREE.NormalBlending;
      distance = Math.min(distance, Math.max(0, distance));
      this.lensFlares.push({
        texture: texture,
        size: size,
        distance: distance,
        x: 0,
        y: 0,
        z: 0,
        scale: 1,
        rotation: 0,
        opacity: opacity,
        color: color,
        blending: blending
      });
    },
    updateLensFlares: function() {
      var f,
          fl = this.lensFlares.length;
      var flare;
      var vecX = -this.positionScreen.x * 2;
      var vecY = -this.positionScreen.y * 2;
      for (f = 0; f < fl; f++) {
        flare = this.lensFlares[f];
        flare.x = this.positionScreen.x + vecX * flare.distance;
        flare.y = this.positionScreen.y + vecY * flare.distance;
        flare.wantedRotation = flare.x * Math.PI * 0.25;
        flare.rotation += (flare.wantedRotation - flare.rotation) * 0.25;
      }
    }
  });
  THREE.Scene = function() {
    THREE.Object3D.call(this);
    this.type = 'Scene';
    this.background = null;
    this.fog = null;
    this.overrideMaterial = null;
    this.autoUpdate = true;
  };
  THREE.Scene.prototype = Object.create(THREE.Object3D.prototype);
  THREE.Scene.prototype.constructor = THREE.Scene;
  THREE.Scene.prototype.copy = function(source, recursive) {
    THREE.Object3D.prototype.copy.call(this, source, recursive);
    if (source.background !== null)
      this.background = source.background.clone();
    if (source.fog !== null)
      this.fog = source.fog.clone();
    if (source.overrideMaterial !== null)
      this.overrideMaterial = source.overrideMaterial.clone();
    this.autoUpdate = source.autoUpdate;
    this.matrixAutoUpdate = source.matrixAutoUpdate;
    return this;
  };
  THREE.Fog = function(color, near, far) {
    this.name = '';
    this.color = new THREE.Color(color);
    this.near = (near !== undefined) ? near : 1;
    this.far = (far !== undefined) ? far : 1000;
  };
  THREE.Fog.prototype.clone = function() {
    return new THREE.Fog(this.color.getHex(), this.near, this.far);
  };
  THREE.FogExp2 = function(color, density) {
    this.name = '';
    this.color = new THREE.Color(color);
    this.density = (density !== undefined) ? density : 0.00025;
  };
  THREE.FogExp2.prototype.clone = function() {
    return new THREE.FogExp2(this.color.getHex(), this.density);
  };
  THREE.ShaderChunk = {};
  THREE.ShaderChunk['alphamap_fragment'] = "#ifdef USE_ALPHAMAP\n	diffuseColor.a *= texture2D( alphaMap, vUv ).g;\n#endif\n";
  THREE.ShaderChunk['alphamap_pars_fragment'] = "#ifdef USE_ALPHAMAP\n	uniform sampler2D alphaMap;\n#endif\n";
  THREE.ShaderChunk['alphatest_fragment'] = "#ifdef ALPHATEST\n	if ( diffuseColor.a < ALPHATEST ) discard;\n#endif\n";
  THREE.ShaderChunk['aomap_fragment'] = "#ifdef USE_AOMAP\n	float ambientOcclusion = ( texture2D( aoMap, vUv2 ).r - 1.0 ) * aoMapIntensity + 1.0;\n	reflectedLight.indirectDiffuse *= ambientOcclusion;\n	#if defined( USE_ENVMAP ) && defined( PHYSICAL )\n		float dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n		reflectedLight.indirectSpecular *= computeSpecularOcclusion( dotNV, ambientOcclusion, material.specularRoughness );\n	#endif\n#endif\n";
  THREE.ShaderChunk['aomap_pars_fragment'] = "#ifdef USE_AOMAP\n	uniform sampler2D aoMap;\n	uniform float aoMapIntensity;\n#endif";
  THREE.ShaderChunk['begin_vertex'] = "\nvec3 transformed = vec3( position );\n";
  THREE.ShaderChunk['beginnormal_vertex'] = "\nvec3 objectNormal = vec3( normal );\n";
  THREE.ShaderChunk['bsdfs'] = "bool testLightInRange( const in float lightDistance, const in float cutoffDistance ) {\n	return any( bvec2( cutoffDistance == 0.0, lightDistance < cutoffDistance ) );\n}\nfloat punctualLightIntensityToIrradianceFactor( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n		if( decayExponent > 0.0 ) {\n#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n			float distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n			float maxDistanceCutoffFactor = pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n			return distanceFalloff * maxDistanceCutoffFactor;\n#else\n			return pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n#endif\n		}\n		return 1.0;\n}\nvec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {\n	return RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {\n	float fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );\n	return ( 1.0 - specularColor ) * fresnel + specularColor;\n}\nfloat G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {\n	float a2 = pow2( alpha );\n	float gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n	float gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n	return 1.0 / ( gl * gv );\n}\nfloat G_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n	float a2 = pow2( alpha );\n	float gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n	float gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n	return 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n	float a2 = pow2( alpha );\n	float denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n	return RECIPROCAL_PI * a2 / pow2( denom );\n}\nvec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n	float alpha = pow2( roughness );\n	vec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n	float dotNL = saturate( dot( geometry.normal, incidentLight.direction ) );\n	float dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n	float dotNH = saturate( dot( geometry.normal, halfDir ) );\n	float dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n	vec3 F = F_Schlick( specularColor, dotLH );\n	float G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n	float D = D_GGX( alpha, dotNH );\n	return F * ( G * D );\n}\nvec3 BRDF_Specular_GGX_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n	float dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n	const vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n	const vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n	vec4 r = roughness * c0 + c1;\n	float a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n	vec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;\n	return specularColor * AB.x + AB.y;\n}\nfloat G_BlinnPhong_Implicit( ) {\n	return 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n	return RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {\n	vec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n	float dotNH = saturate( dot( geometry.normal, halfDir ) );\n	float dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n	vec3 F = F_Schlick( specularColor, dotLH );\n	float G = G_BlinnPhong_Implicit( );\n	float D = D_BlinnPhong( shininess, dotNH );\n	return F * ( G * D );\n}\nfloat GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {\n	return ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );\n}\nfloat BlinnExponentToGGXRoughness( const in float blinnExponent ) {\n	return sqrt( 2.0 / ( blinnExponent + 2.0 ) );\n}\n";
  THREE.ShaderChunk['bumpmap_pars_fragment'] = "#ifdef USE_BUMPMAP\n	uniform sampler2D bumpMap;\n	uniform float bumpScale;\n	vec2 dHdxy_fwd() {\n		vec2 dSTdx = dFdx( vUv );\n		vec2 dSTdy = dFdy( vUv );\n		float Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n		float dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n		float dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n		return vec2( dBx, dBy );\n	}\n	vec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {\n		vec3 vSigmaX = dFdx( surf_pos );\n		vec3 vSigmaY = dFdy( surf_pos );\n		vec3 vN = surf_norm;\n		vec3 R1 = cross( vSigmaY, vN );\n		vec3 R2 = cross( vN, vSigmaX );\n		float fDet = dot( vSigmaX, R1 );\n		vec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n		return normalize( abs( fDet ) * surf_norm - vGrad );\n	}\n#endif\n";
  THREE.ShaderChunk['clipping_planes_fragment'] = "#if NUM_CLIPPING_PLANES > 0\n	for ( int i = 0; i < NUM_CLIPPING_PLANES; ++ i ) {\n		vec4 plane = clippingPlanes[ i ];\n		if ( dot( vViewPosition, plane.xyz ) > plane.w ) discard;\n	}\n#endif\n";
  THREE.ShaderChunk['clipping_planes_pars_fragment'] = "#if NUM_CLIPPING_PLANES > 0\n	#if ! defined( PHYSICAL ) && ! defined( PHONG )\n		varying vec3 vViewPosition;\n	#endif\n	uniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif\n";
  THREE.ShaderChunk['clipping_planes_pars_vertex'] = "#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG )\n	varying vec3 vViewPosition;\n#endif\n";
  THREE.ShaderChunk['clipping_planes_vertex'] = "#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG )\n	vViewPosition = - mvPosition.xyz;\n#endif\n";
  THREE.ShaderChunk['color_fragment'] = "#ifdef USE_COLOR\n	diffuseColor.rgb *= vColor;\n#endif";
  THREE.ShaderChunk['color_pars_fragment'] = "#ifdef USE_COLOR\n	varying vec3 vColor;\n#endif\n";
  THREE.ShaderChunk['color_pars_vertex'] = "#ifdef USE_COLOR\n	varying vec3 vColor;\n#endif";
  THREE.ShaderChunk['color_vertex'] = "#ifdef USE_COLOR\n	vColor.xyz = color.xyz;\n#endif";
  THREE.ShaderChunk['common'] = "#define PI 3.14159265359\n#define PI2 6.28318530718\n#define RECIPROCAL_PI 0.31830988618\n#define RECIPROCAL_PI2 0.15915494\n#define LOG2 1.442695\n#define EPSILON 1e-6\n#define saturate(a) clamp( a, 0.0, 1.0 )\n#define whiteCompliment(a) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }\nhighp float rand( const in vec2 uv ) {\n	const highp float a = 12.9898, b = 78.233, c = 43758.5453;\n	highp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n	return fract(sin(sn) * c);\n}\nstruct IncidentLight {\n	vec3 color;\n	vec3 direction;\n	bool visible;\n};\nstruct ReflectedLight {\n	vec3 directDiffuse;\n	vec3 directSpecular;\n	vec3 indirectDiffuse;\n	vec3 indirectSpecular;\n};\nstruct GeometricContext {\n	vec3 position;\n	vec3 normal;\n	vec3 viewDir;\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n	return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n	return normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nvec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n	float distance = dot( planeNormal, point - pointOnPlane );\n	return - distance * planeNormal + point;\n}\nfloat sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n	return sign( dot( point - pointOnPlane, planeNormal ) );\n}\nvec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {\n	return lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;\n}\n";
  THREE.ShaderChunk['cube_uv_reflection_fragment'] = "#ifdef ENVMAP_TYPE_CUBE_UV\n#define cubeUV_textureSize (1024.0)\nint getFaceFromDirection(vec3 direction) {\n	vec3 absDirection = abs(direction);\n	int face = -1;\n	if( absDirection.x > absDirection.z ) {\n		if(absDirection.x > absDirection.y )\n			face = direction.x > 0.0 ? 0 : 3;\n		else\n			face = direction.y > 0.0 ? 1 : 4;\n	}\n	else {\n		if(absDirection.z > absDirection.y )\n			face = direction.z > 0.0 ? 2 : 5;\n		else\n			face = direction.y > 0.0 ? 1 : 4;\n	}\n	return face;\n}\n#define cubeUV_maxLods1  (log2(cubeUV_textureSize*0.25) - 1.0)\n#define cubeUV_rangeClamp (exp2((6.0 - 1.0) * 2.0))\nvec2 MipLevelInfo( vec3 vec, float roughnessLevel, float roughness ) {\n	float scale = exp2(cubeUV_maxLods1 - roughnessLevel);\n	float dxRoughness = dFdx(roughness);\n	float dyRoughness = dFdy(roughness);\n	vec3 dx = dFdx( vec * scale * dxRoughness );\n	vec3 dy = dFdy( vec * scale * dyRoughness );\n	float d = max( dot( dx, dx ), dot( dy, dy ) );\n	d = clamp(d, 1.0, cubeUV_rangeClamp);\n	float mipLevel = 0.5 * log2(d);\n	return vec2(floor(mipLevel), fract(mipLevel));\n}\n#define cubeUV_maxLods2 (log2(cubeUV_textureSize*0.25) - 2.0)\n#define cubeUV_rcpTextureSize (1.0 / cubeUV_textureSize)\nvec2 getCubeUV(vec3 direction, float roughnessLevel, float mipLevel) {\n	mipLevel = roughnessLevel > cubeUV_maxLods2 - 3.0 ? 0.0 : mipLevel;\n	float a = 16.0 * cubeUV_rcpTextureSize;\n	vec2 exp2_packed = exp2( vec2( roughnessLevel, mipLevel ) );\n	vec2 rcp_exp2_packed = vec2( 1.0 ) / exp2_packed;\n	float powScale = exp2_packed.x * exp2_packed.y;\n	float scale = rcp_exp2_packed.x * rcp_exp2_packed.y * 0.25;\n	float mipOffset = 0.75*(1.0 - rcp_exp2_packed.y) * rcp_exp2_packed.x;\n	bool bRes = mipLevel == 0.0;\n	scale =  bRes && (scale < a) ? a : scale;\n	vec3 r;\n	vec2 offset;\n	int face = getFaceFromDirection(direction);\n	float rcpPowScale = 1.0 / powScale;\n	if( face == 0) {\n		r = vec3(direction.x, -direction.z, direction.y);\n		offset = vec2(0.0+mipOffset,0.75 * rcpPowScale);\n		offset.y = bRes && (offset.y < 2.0*a) ?  a : offset.y;\n	}\n	else if( face == 1) {\n		r = vec3(direction.y, direction.x, direction.z);\n		offset = vec2(scale+mipOffset, 0.75 * rcpPowScale);\n		offset.y = bRes && (offset.y < 2.0*a) ?  a : offset.y;\n	}\n	else if( face == 2) {\n		r = vec3(direction.z, direction.x, direction.y);\n		offset = vec2(2.0*scale+mipOffset, 0.75 * rcpPowScale);\n		offset.y = bRes && (offset.y < 2.0*a) ?  a : offset.y;\n	}\n	else if( face == 3) {\n		r = vec3(direction.x, direction.z, direction.y);\n		offset = vec2(0.0+mipOffset,0.5 * rcpPowScale);\n		offset.y = bRes && (offset.y < 2.0*a) ?  0.0 : offset.y;\n	}\n	else if( face == 4) {\n		r = vec3(direction.y, direction.x, -direction.z);\n		offset = vec2(scale+mipOffset, 0.5 * rcpPowScale);\n		offset.y = bRes && (offset.y < 2.0*a) ?  0.0 : offset.y;\n	}\n	else {\n		r = vec3(direction.z, -direction.x, direction.y);\n		offset = vec2(2.0*scale+mipOffset, 0.5 * rcpPowScale);\n		offset.y = bRes && (offset.y < 2.0*a) ?  0.0 : offset.y;\n	}\n	r = normalize(r);\n	float texelOffset = 0.5 * cubeUV_rcpTextureSize;\n	vec2 s = ( r.yz / abs( r.x ) + vec2( 1.0 ) ) * 0.5;\n	vec2 base = offset + vec2( texelOffset );\n	return base + s * ( scale - 2.0 * texelOffset );\n}\n#define cubeUV_maxLods3 (log2(cubeUV_textureSize*0.25) - 3.0)\nvec4 textureCubeUV(vec3 reflectedDirection, float roughness ) {\n	float roughnessVal = roughness* cubeUV_maxLods3;\n	float r1 = floor(roughnessVal);\n	float r2 = r1 + 1.0;\n	float t = fract(roughnessVal);\n	vec2 mipInfo = MipLevelInfo(reflectedDirection, r1, roughness);\n	float s = mipInfo.y;\n	float level0 = mipInfo.x;\n	float level1 = level0 + 1.0;\n	level1 = level1 > 5.0 ? 5.0 : level1;\n	level0 += min( floor( s + 0.5 ), 5.0 );\n	vec2 uv_10 = getCubeUV(reflectedDirection, r1, level0);\n	vec4 color10 = envMapTexelToLinear(texture2D(envMap, uv_10));\n	vec2 uv_20 = getCubeUV(reflectedDirection, r2, level0);\n	vec4 color20 = envMapTexelToLinear(texture2D(envMap, uv_20));\n	vec4 result = mix(color10, color20, t);\n	return vec4(result.rgb, 1.0);\n}\n#endif\n";
  THREE.ShaderChunk['defaultnormal_vertex'] = "#ifdef FLIP_SIDED\n	objectNormal = -objectNormal;\n#endif\nvec3 transformedNormal = normalMatrix * objectNormal;\n";
  THREE.ShaderChunk['displacementmap_vertex'] = "#ifdef USE_DISPLACEMENTMAP\n	transformed += normal * ( texture2D( displacementMap, uv ).x * displacementScale + displacementBias );\n#endif\n";
  THREE.ShaderChunk['displacementmap_pars_vertex'] = "#ifdef USE_DISPLACEMENTMAP\n	uniform sampler2D displacementMap;\n	uniform float displacementScale;\n	uniform float displacementBias;\n#endif\n";
  THREE.ShaderChunk['emissivemap_fragment'] = "#ifdef USE_EMISSIVEMAP\n	vec4 emissiveColor = texture2D( emissiveMap, vUv );\n	emissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb;\n	totalEmissiveRadiance *= emissiveColor.rgb;\n#endif\n";
  THREE.ShaderChunk['emissivemap_pars_fragment'] = "#ifdef USE_EMISSIVEMAP\n	uniform sampler2D emissiveMap;\n#endif\n";
  THREE.ShaderChunk['encodings_pars_fragment'] = "\nvec4 LinearToLinear( in vec4 value ) {\n  return value;\n}\nvec4 GammaToLinear( in vec4 value, in float gammaFactor ) {\n  return vec4( pow( value.xyz, vec3( gammaFactor ) ), value.w );\n}\nvec4 LinearToGamma( in vec4 value, in float gammaFactor ) {\n  return vec4( pow( value.xyz, vec3( 1.0 / gammaFactor ) ), value.w );\n}\nvec4 sRGBToLinear( in vec4 value ) {\n  return vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.w );\n}\nvec4 LinearTosRGB( in vec4 value ) {\n  return vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.w );\n}\nvec4 RGBEToLinear( in vec4 value ) {\n  return vec4( value.rgb * exp2( value.a * 255.0 - 128.0 ), 1.0 );\n}\nvec4 LinearToRGBE( in vec4 value ) {\n  float maxComponent = max( max( value.r, value.g ), value.b );\n  float fExp = clamp( ceil( log2( maxComponent ) ), -128.0, 127.0 );\n  return vec4( value.rgb / exp2( fExp ), ( fExp + 128.0 ) / 255.0 );\n}\nvec4 RGBMToLinear( in vec4 value, in float maxRange ) {\n  return vec4( value.xyz * value.w * maxRange, 1.0 );\n}\nvec4 LinearToRGBM( in vec4 value, in float maxRange ) {\n  float maxRGB = max( value.x, max( value.g, value.b ) );\n  float M      = clamp( maxRGB / maxRange, 0.0, 1.0 );\n  M            = ceil( M * 255.0 ) / 255.0;\n  return vec4( value.rgb / ( M * maxRange ), M );\n}\nvec4 RGBDToLinear( in vec4 value, in float maxRange ) {\n    return vec4( value.rgb * ( ( maxRange / 255.0 ) / value.a ), 1.0 );\n}\nvec4 LinearToRGBD( in vec4 value, in float maxRange ) {\n    float maxRGB = max( value.x, max( value.g, value.b ) );\n    float D      = max( maxRange / maxRGB, 1.0 );\n    D            = min( floor( D ) / 255.0, 1.0 );\n    return vec4( value.rgb * ( D * ( 255.0 / maxRange ) ), D );\n}\nconst mat3 cLogLuvM = mat3( 0.2209, 0.3390, 0.4184, 0.1138, 0.6780, 0.7319, 0.0102, 0.1130, 0.2969 );\nvec4 LinearToLogLuv( in vec4 value )  {\n  vec3 Xp_Y_XYZp = value.rgb * cLogLuvM;\n  Xp_Y_XYZp = max(Xp_Y_XYZp, vec3(1e-6, 1e-6, 1e-6));\n  vec4 vResult;\n  vResult.xy = Xp_Y_XYZp.xy / Xp_Y_XYZp.z;\n  float Le = 2.0 * log2(Xp_Y_XYZp.y) + 127.0;\n  vResult.w = fract(Le);\n  vResult.z = (Le - (floor(vResult.w*255.0))/255.0)/255.0;\n  return vResult;\n}\nconst mat3 cLogLuvInverseM = mat3( 6.0014, -2.7008, -1.7996, -1.3320, 3.1029, -5.7721, 0.3008, -1.0882, 5.6268 );\nvec4 LogLuvToLinear( in vec4 value ) {\n  float Le = value.z * 255.0 + value.w;\n  vec3 Xp_Y_XYZp;\n  Xp_Y_XYZp.y = exp2((Le - 127.0) / 2.0);\n  Xp_Y_XYZp.z = Xp_Y_XYZp.y / value.y;\n  Xp_Y_XYZp.x = value.x * Xp_Y_XYZp.z;\n  vec3 vRGB = Xp_Y_XYZp.rgb * cLogLuvInverseM;\n  return vec4( max(vRGB, 0.0), 1.0 );\n}\n";
  THREE.ShaderChunk['encodings_fragment'] = "  gl_FragColor = linearToOutputTexel( gl_FragColor );\n";
  THREE.ShaderChunk['envmap_fragment'] = "#ifdef USE_ENVMAP\n	#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n		vec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );\n		vec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n		#ifdef ENVMAP_MODE_REFLECTION\n			vec3 reflectVec = reflect( cameraToVertex, worldNormal );\n		#else\n			vec3 reflectVec = refract( cameraToVertex, worldNormal, refractionRatio );\n		#endif\n	#else\n		vec3 reflectVec = vReflect;\n	#endif\n	#ifdef ENVMAP_TYPE_CUBE\n		vec4 envColor = textureCube( envMap, flipNormal * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n	#elif defined( ENVMAP_TYPE_EQUIREC )\n		vec2 sampleUV;\n		sampleUV.y = saturate( flipNormal * reflectVec.y * 0.5 + 0.5 );\n		sampleUV.x = atan( flipNormal * reflectVec.z, flipNormal * reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n		vec4 envColor = texture2D( envMap, sampleUV );\n	#elif defined( ENVMAP_TYPE_SPHERE )\n		vec3 reflectView = flipNormal * normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0, 0.0, 1.0 ) );\n		vec4 envColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5 );\n	#endif\n	envColor = envMapTexelToLinear( envColor );\n	#ifdef ENVMAP_BLENDING_MULTIPLY\n		outgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n	#elif defined( ENVMAP_BLENDING_MIX )\n		outgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n	#elif defined( ENVMAP_BLENDING_ADD )\n		outgoingLight += envColor.xyz * specularStrength * reflectivity;\n	#endif\n#endif\n";
  THREE.ShaderChunk['envmap_pars_fragment'] = "#if defined( USE_ENVMAP ) || defined( PHYSICAL )\n	uniform float reflectivity;\n	uniform float envMapIntenstiy;\n#endif\n#ifdef USE_ENVMAP\n	#if ! defined( PHYSICAL ) && ( defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) )\n		varying vec3 vWorldPosition;\n	#endif\n	#ifdef ENVMAP_TYPE_CUBE\n		uniform samplerCube envMap;\n	#else\n		uniform sampler2D envMap;\n	#endif\n	uniform float flipEnvMap;\n	#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( PHYSICAL )\n		uniform float refractionRatio;\n	#else\n		varying vec3 vReflect;\n	#endif\n#endif\n";
  THREE.ShaderChunk['envmap_pars_vertex'] = "#ifdef USE_ENVMAP\n	#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n		varying vec3 vWorldPosition;\n	#else\n		varying vec3 vReflect;\n		uniform float refractionRatio;\n	#endif\n#endif\n";
  THREE.ShaderChunk['envmap_vertex'] = "#ifdef USE_ENVMAP\n	#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n		vWorldPosition = worldPosition.xyz;\n	#else\n		vec3 cameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n		vec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n		#ifdef ENVMAP_MODE_REFLECTION\n			vReflect = reflect( cameraToVertex, worldNormal );\n		#else\n			vReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n		#endif\n	#endif\n#endif\n";
  THREE.ShaderChunk['fog_fragment'] = "#ifdef USE_FOG\n	#ifdef USE_LOGDEPTHBUF_EXT\n		float depth = gl_FragDepthEXT / gl_FragCoord.w;\n	#else\n		float depth = gl_FragCoord.z / gl_FragCoord.w;\n	#endif\n	#ifdef FOG_EXP2\n		float fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * depth * depth * LOG2 ) );\n	#else\n		float fogFactor = smoothstep( fogNear, fogFar, depth );\n	#endif\n	gl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif\n";
  THREE.ShaderChunk['fog_pars_fragment'] = "#ifdef USE_FOG\n	uniform vec3 fogColor;\n	#ifdef FOG_EXP2\n		uniform float fogDensity;\n	#else\n		uniform float fogNear;\n		uniform float fogFar;\n	#endif\n#endif";
  THREE.ShaderChunk['lightmap_fragment'] = "#ifdef USE_LIGHTMAP\n	reflectedLight.indirectDiffuse += PI * texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n#endif\n";
  THREE.ShaderChunk['lightmap_pars_fragment'] = "#ifdef USE_LIGHTMAP\n	uniform sampler2D lightMap;\n	uniform float lightMapIntensity;\n#endif";
  THREE.ShaderChunk['lights_lambert_vertex'] = "vec3 diffuse = vec3( 1.0 );\nGeometricContext geometry;\ngeometry.position = mvPosition.xyz;\ngeometry.normal = normalize( transformedNormal );\ngeometry.viewDir = normalize( -mvPosition.xyz );\nGeometricContext backGeometry;\nbackGeometry.position = geometry.position;\nbackGeometry.normal = -geometry.normal;\nbackGeometry.viewDir = geometry.viewDir;\nvLightFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\n	vLightBack = vec3( 0.0 );\n#endif\nIncidentLight directLight;\nfloat dotNL;\nvec3 directLightColor_Diffuse;\n#if NUM_POINT_LIGHTS > 0\n	for ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n		getPointDirectLightIrradiance( pointLights[ i ], geometry, directLight );\n		dotNL = dot( geometry.normal, directLight.direction );\n		directLightColor_Diffuse = PI * directLight.color;\n		vLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n		#ifdef DOUBLE_SIDED\n			vLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n		#endif\n	}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n	for ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n		getSpotDirectLightIrradiance( spotLights[ i ], geometry, directLight );\n		dotNL = dot( geometry.normal, directLight.direction );\n		directLightColor_Diffuse = PI * directLight.color;\n		vLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n		#ifdef DOUBLE_SIDED\n			vLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n		#endif\n	}\n#endif\n#if NUM_DIR_LIGHTS > 0\n	for ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n		getDirectionalDirectLightIrradiance( directionalLights[ i ], geometry, directLight );\n		dotNL = dot( geometry.normal, directLight.direction );\n		directLightColor_Diffuse = PI * directLight.color;\n		vLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n		#ifdef DOUBLE_SIDED\n			vLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n		#endif\n	}\n#endif\n#if NUM_HEMI_LIGHTS > 0\n	for ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n		vLightFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n		#ifdef DOUBLE_SIDED\n			vLightBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry );\n		#endif\n	}\n#endif\n";
  THREE.ShaderChunk['lights_pars'] = "uniform vec3 ambientLightColor;\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n	vec3 irradiance = ambientLightColor;\n	#ifndef PHYSICALLY_CORRECT_LIGHTS\n		irradiance *= PI;\n	#endif\n	return irradiance;\n}\n#if NUM_DIR_LIGHTS > 0\n	struct DirectionalLight {\n		vec3 direction;\n		vec3 color;\n		int shadow;\n		float shadowBias;\n		float shadowRadius;\n		vec2 shadowMapSize;\n	};\n	uniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n	void getDirectionalDirectLightIrradiance( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n		directLight.color = directionalLight.color;\n		directLight.direction = directionalLight.direction;\n		directLight.visible = true;\n	}\n#endif\n#if NUM_POINT_LIGHTS > 0\n	struct PointLight {\n		vec3 position;\n		vec3 color;\n		float distance;\n		float decay;\n		int shadow;\n		float shadowBias;\n		float shadowRadius;\n		vec2 shadowMapSize;\n	};\n	uniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n	void getPointDirectLightIrradiance( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n		vec3 lVector = pointLight.position - geometry.position;\n		directLight.direction = normalize( lVector );\n		float lightDistance = length( lVector );\n		if ( testLightInRange( lightDistance, pointLight.distance ) ) {\n			directLight.color = pointLight.color;\n			directLight.color *= punctualLightIntensityToIrradianceFactor( lightDistance, pointLight.distance, pointLight.decay );\n			directLight.visible = true;\n		} else {\n			directLight.color = vec3( 0.0 );\n			directLight.visible = false;\n		}\n	}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n	struct SpotLight {\n		vec3 position;\n		vec3 direction;\n		vec3 color;\n		float distance;\n		float decay;\n		float coneCos;\n		float penumbraCos;\n		int shadow;\n		float shadowBias;\n		float shadowRadius;\n		vec2 shadowMapSize;\n	};\n	uniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n	void getSpotDirectLightIrradiance( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight directLight  ) {\n		vec3 lVector = spotLight.position - geometry.position;\n		directLight.direction = normalize( lVector );\n		float lightDistance = length( lVector );\n		float angleCos = dot( directLight.direction, spotLight.direction );\n		if ( all( bvec2( angleCos > spotLight.coneCos, testLightInRange( lightDistance, spotLight.distance ) ) ) ) {\n			float spotEffect = smoothstep( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n			directLight.color = spotLight.color;\n			directLight.color *= spotEffect * punctualLightIntensityToIrradianceFactor( lightDistance, spotLight.distance, spotLight.decay );\n			directLight.visible = true;\n		} else {\n			directLight.color = vec3( 0.0 );\n			directLight.visible = false;\n		}\n	}\n#endif\n#if NUM_HEMI_LIGHTS > 0\n	struct HemisphereLight {\n		vec3 direction;\n		vec3 skyColor;\n		vec3 groundColor;\n	};\n	uniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n	vec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in GeometricContext geometry ) {\n		float dotNL = dot( geometry.normal, hemiLight.direction );\n		float hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n		vec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n		#ifndef PHYSICALLY_CORRECT_LIGHTS\n			irradiance *= PI;\n		#endif\n		return irradiance;\n	}\n#endif\n#if defined( USE_ENVMAP ) && defined( PHYSICAL )\n	vec3 getLightProbeIndirectIrradiance( const in GeometricContext geometry, const in int maxMIPLevel ) {\n		#include <normal_flip>\n		vec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n		#ifdef ENVMAP_TYPE_CUBE\n			vec3 queryVec = flipNormal * vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n			#ifdef TEXTURE_LOD_EXT\n				vec4 envMapColor = textureCubeLodEXT( envMap, queryVec, float( maxMIPLevel ) );\n			#else\n				vec4 envMapColor = textureCube( envMap, queryVec, float( maxMIPLevel ) );\n			#endif\n			envMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n		#elif defined( ENVMAP_TYPE_CUBE_UV )\n			vec3 queryVec = flipNormal * vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n			vec4 envMapColor = textureCubeUV( queryVec, 1.0 );\n		#else\n			vec4 envMapColor = vec4( 0.0 );\n		#endif\n		return PI * envMapColor.rgb * envMapIntensity;\n	}\n	float getSpecularMIPLevel( const in float blinnShininessExponent, const in int maxMIPLevel ) {\n		float maxMIPLevelScalar = float( maxMIPLevel );\n		float desiredMIPLevel = maxMIPLevelScalar - 0.79248 - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );\n		return clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );\n	}\n	vec3 getLightProbeIndirectRadiance( const in GeometricContext geometry, const in float blinnShininessExponent, const in int maxMIPLevel ) {\n		#ifdef ENVMAP_MODE_REFLECTION\n			vec3 reflectVec = reflect( -geometry.viewDir, geometry.normal );\n		#else\n			vec3 reflectVec = refract( -geometry.viewDir, geometry.normal, refractionRatio );\n		#endif\n		#include <normal_flip>\n		reflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n		float specularMIPLevel = getSpecularMIPLevel( blinnShininessExponent, maxMIPLevel );\n		#ifdef ENVMAP_TYPE_CUBE\n			vec3 queryReflectVec = flipNormal * vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n			#ifdef TEXTURE_LOD_EXT\n				vec4 envMapColor = textureCubeLodEXT( envMap, queryReflectVec, specularMIPLevel );\n			#else\n				vec4 envMapColor = textureCube( envMap, queryReflectVec, specularMIPLevel );\n			#endif\n			envMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n		#elif defined( ENVMAP_TYPE_CUBE_UV )\n			vec3 queryReflectVec = flipNormal * vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n			vec4 envMapColor = textureCubeUV(queryReflectVec, BlinnExponentToGGXRoughness(blinnShininessExponent));\n		#elif defined( ENVMAP_TYPE_EQUIREC )\n			vec2 sampleUV;\n			sampleUV.y = saturate( flipNormal * reflectVec.y * 0.5 + 0.5 );\n			sampleUV.x = atan( flipNormal * reflectVec.z, flipNormal * reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n			#ifdef TEXTURE_LOD_EXT\n				vec4 envMapColor = texture2DLodEXT( envMap, sampleUV, specularMIPLevel );\n			#else\n				vec4 envMapColor = texture2D( envMap, sampleUV, specularMIPLevel );\n			#endif\n			envMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n		#elif defined( ENVMAP_TYPE_SPHERE )\n			vec3 reflectView = flipNormal * normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0,0.0,1.0 ) );\n			#ifdef TEXTURE_LOD_EXT\n				vec4 envMapColor = texture2DLodEXT( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n			#else\n				vec4 envMapColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n			#endif\n			envMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n		#endif\n		return envMapColor.rgb * envMapIntensity;\n	}\n#endif\n";
  THREE.ShaderChunk['lights_phong_fragment'] = "BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;\n";
  THREE.ShaderChunk['lights_phong_pars_fragment'] = "varying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n	varying vec3 vNormal;\n#endif\nstruct BlinnPhongMaterial {\n	vec3	diffuseColor;\n	vec3	specularColor;\n	float	specularShininess;\n	float	specularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n	float dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n	vec3 irradiance = dotNL * directLight.color;\n	#ifndef PHYSICALLY_CORRECT_LIGHTS\n		irradiance *= PI;\n	#endif\n	reflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n	reflectedLight.directSpecular += irradiance * BRDF_Specular_BlinnPhong( directLight, geometry, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n	reflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\n#define RE_Direct				RE_Direct_BlinnPhong\n#define RE_IndirectDiffuse		RE_IndirectDiffuse_BlinnPhong\n#define Material_LightProbeLOD( material )	(0)\n";
  THREE.ShaderChunk['lights_physical_fragment'] = "PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nmaterial.specularRoughness = clamp( roughnessFactor, 0.04, 1.0 );\n#ifdef STANDARD\n	material.specularColor = mix( vec3( DEFAULT_SPECULAR_COEFFICIENT ), diffuseColor.rgb, metalnessFactor );\n#else\n	material.specularColor = mix( vec3( MAXIMUM_SPECULAR_COEFFICIENT * pow2( reflectivity ) ), diffuseColor.rgb, metalnessFactor );\n	material.clearCoat = saturate( clearCoat );	material.clearCoatRoughness = clamp( clearCoatRoughness, 0.04, 1.0 );\n#endif\n";
  THREE.ShaderChunk['lights_physical_pars_fragment'] = "struct PhysicalMaterial {\n	vec3	diffuseColor;\n	float	specularRoughness;\n	vec3	specularColor;\n	#ifndef STANDARD\n		float clearCoat;\n		float clearCoatRoughness;\n	#endif\n};\n#define MAXIMUM_SPECULAR_COEFFICIENT 0.16\n#define DEFAULT_SPECULAR_COEFFICIENT 0.04\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n	float dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n	vec3 irradiance = dotNL * directLight.color;\n	#ifndef PHYSICALLY_CORRECT_LIGHTS\n		irradiance *= PI;\n	#endif\n	reflectedLight.directSpecular += irradiance * BRDF_Specular_GGX( directLight, geometry, material.specularColor, material.specularRoughness );\n	reflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n	#ifndef STANDARD\n		reflectedLight.directSpecular += irradiance * material.clearCoat * BRDF_Specular_GGX( directLight, geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n	#endif\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n	reflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 clearCoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n	reflectedLight.indirectSpecular += radiance * BRDF_Specular_GGX_Environment( geometry, material.specularColor, material.specularRoughness );\n	#ifndef STANDARD\n		reflectedLight.indirectSpecular += clearCoatRadiance * material.clearCoat * BRDF_Specular_GGX_Environment( geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n	#endif\n}\n#define RE_Direct				RE_Direct_Physical\n#define RE_IndirectDiffuse		RE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular		RE_IndirectSpecular_Physical\n#define Material_BlinnShininessExponent( material )   GGXRoughnessToBlinnExponent( material.specularRoughness )\n#define Material_ClearCoat_BlinnShininessExponent( material )   GGXRoughnessToBlinnExponent( material.clearCoatRoughness )\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n	return saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}\n";
  THREE.ShaderChunk['lights_template'] = "\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = normalize( vViewPosition );\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n	PointLight pointLight;\n	for ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n		pointLight = pointLights[ i ];\n		getPointDirectLightIrradiance( pointLight, geometry, directLight );\n		#ifdef USE_SHADOWMAP\n		directLight.color *= all( bvec2( pointLight.shadow, directLight.visible ) ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ] ) : 1.0;\n		#endif\n		RE_Direct( directLight, geometry, material, reflectedLight );\n	}\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n	SpotLight spotLight;\n	for ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n		spotLight = spotLights[ i ];\n		getSpotDirectLightIrradiance( spotLight, geometry, directLight );\n		#ifdef USE_SHADOWMAP\n		directLight.color *= all( bvec2( spotLight.shadow, directLight.visible ) ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n		#endif\n		RE_Direct( directLight, geometry, material, reflectedLight );\n	}\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n	DirectionalLight directionalLight;\n	for ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n		directionalLight = directionalLights[ i ];\n		getDirectionalDirectLightIrradiance( directionalLight, geometry, directLight );\n		#ifdef USE_SHADOWMAP\n		directLight.color *= all( bvec2( directionalLight.shadow, directLight.visible ) ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n		#endif\n		RE_Direct( directLight, geometry, material, reflectedLight );\n	}\n#endif\n#if defined( RE_IndirectDiffuse )\n	vec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n	#ifdef USE_LIGHTMAP\n		vec3 lightMapIrradiance = texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n		#ifndef PHYSICALLY_CORRECT_LIGHTS\n			lightMapIrradiance *= PI;\n		#endif\n		irradiance += lightMapIrradiance;\n	#endif\n	#if ( NUM_HEMI_LIGHTS > 0 )\n		for ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n			irradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n		}\n	#endif\n	#if defined( USE_ENVMAP ) && defined( PHYSICAL ) && defined( ENVMAP_TYPE_CUBE_UV )\n	 	irradiance += getLightProbeIndirectIrradiance( geometry, 8 );\n	#endif\n	RE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n	vec3 radiance = getLightProbeIndirectRadiance( geometry, Material_BlinnShininessExponent( material ), 8 );\n	#ifndef STANDARD\n		vec3 clearCoatRadiance = getLightProbeIndirectRadiance( geometry, Material_ClearCoat_BlinnShininessExponent( material ), 8 );\n	#else\n		vec3 clearCoatRadiance = vec3( 0.0 );\n	#endif\n		\n	RE_IndirectSpecular( radiance, clearCoatRadiance, geometry, material, reflectedLight );\n#endif\n";
  THREE.ShaderChunk['logdepthbuf_fragment'] = "#if defined(USE_LOGDEPTHBUF) && defined(USE_LOGDEPTHBUF_EXT)\n	gl_FragDepthEXT = log2(vFragDepth) * logDepthBufFC * 0.5;\n#endif";
  THREE.ShaderChunk['logdepthbuf_pars_fragment'] = "#ifdef USE_LOGDEPTHBUF\n	uniform float logDepthBufFC;\n	#ifdef USE_LOGDEPTHBUF_EXT\n		varying float vFragDepth;\n	#endif\n#endif\n";
  THREE.ShaderChunk['logdepthbuf_pars_vertex'] = "#ifdef USE_LOGDEPTHBUF\n	#ifdef USE_LOGDEPTHBUF_EXT\n		varying float vFragDepth;\n	#endif\n	uniform float logDepthBufFC;\n#endif";
  THREE.ShaderChunk['logdepthbuf_vertex'] = "#ifdef USE_LOGDEPTHBUF\n	gl_Position.z = log2(max( EPSILON, gl_Position.w + 1.0 )) * logDepthBufFC;\n	#ifdef USE_LOGDEPTHBUF_EXT\n		vFragDepth = 1.0 + gl_Position.w;\n	#else\n		gl_Position.z = (gl_Position.z - 1.0) * gl_Position.w;\n	#endif\n#endif\n";
  THREE.ShaderChunk['map_fragment'] = "#ifdef USE_MAP\n	vec4 texelColor = texture2D( map, vUv );\n	texelColor = mapTexelToLinear( texelColor );\n	diffuseColor *= texelColor;\n#endif\n";
  THREE.ShaderChunk['map_pars_fragment'] = "#ifdef USE_MAP\n	uniform sampler2D map;\n#endif\n";
  THREE.ShaderChunk['map_particle_fragment'] = "#ifdef USE_MAP\n	vec4 mapTexel = texture2D( map, vec2( gl_PointCoord.x, 1.0 - gl_PointCoord.y ) * offsetRepeat.zw + offsetRepeat.xy );\n	diffuseColor *= mapTexelToLinear( mapTexel );\n#endif\n";
  THREE.ShaderChunk['map_particle_pars_fragment'] = "#ifdef USE_MAP\n	uniform vec4 offsetRepeat;\n	uniform sampler2D map;\n#endif\n";
  THREE.ShaderChunk['metalnessmap_fragment'] = "float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n	vec4 texelMetalness = texture2D( metalnessMap, vUv );\n	metalnessFactor *= texelMetalness.r;\n#endif\n";
  THREE.ShaderChunk['metalnessmap_pars_fragment'] = "#ifdef USE_METALNESSMAP\n	uniform sampler2D metalnessMap;\n#endif";
  THREE.ShaderChunk['morphnormal_vertex'] = "#ifdef USE_MORPHNORMALS\n	objectNormal += ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];\n	objectNormal += ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];\n	objectNormal += ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];\n	objectNormal += ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];\n#endif\n";
  THREE.ShaderChunk['morphtarget_pars_vertex'] = "#ifdef USE_MORPHTARGETS\n	#ifndef USE_MORPHNORMALS\n	uniform float morphTargetInfluences[ 8 ];\n	#else\n	uniform float morphTargetInfluences[ 4 ];\n	#endif\n#endif";
  THREE.ShaderChunk['morphtarget_vertex'] = "#ifdef USE_MORPHTARGETS\n	transformed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];\n	transformed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];\n	transformed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];\n	transformed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];\n	#ifndef USE_MORPHNORMALS\n	transformed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];\n	transformed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];\n	transformed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];\n	transformed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];\n	#endif\n#endif\n";
  THREE.ShaderChunk['normal_flip'] = "#ifdef DOUBLE_SIDED\n	float flipNormal = ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n#else\n	float flipNormal = 1.0;\n#endif\n";
  THREE.ShaderChunk['normal_fragment'] = "#ifdef FLAT_SHADED\n	vec3 fdx = vec3( dFdx( vViewPosition.x ), dFdx( vViewPosition.y ), dFdx( vViewPosition.z ) );\n	vec3 fdy = vec3( dFdy( vViewPosition.x ), dFdy( vViewPosition.y ), dFdy( vViewPosition.z ) );\n	vec3 normal = normalize( cross( fdx, fdy ) );\n#else\n	vec3 normal = normalize( vNormal ) * flipNormal;\n#endif\n#ifdef USE_NORMALMAP\n	normal = perturbNormal2Arb( -vViewPosition, normal );\n#elif defined( USE_BUMPMAP )\n	normal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\n#endif\n";
  THREE.ShaderChunk['normalmap_pars_fragment'] = "#ifdef USE_NORMALMAP\n	uniform sampler2D normalMap;\n	uniform vec2 normalScale;\n	vec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) {\n		vec3 q0 = dFdx( eye_pos.xyz );\n		vec3 q1 = dFdy( eye_pos.xyz );\n		vec2 st0 = dFdx( vUv.st );\n		vec2 st1 = dFdy( vUv.st );\n		vec3 S = normalize( q0 * st1.t - q1 * st0.t );\n		vec3 T = normalize( -q0 * st1.s + q1 * st0.s );\n		vec3 N = normalize( surf_norm );\n		vec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n		mapN.xy = normalScale * mapN.xy;\n		mat3 tsn = mat3( S, T, N );\n		return normalize( tsn * mapN );\n	}\n#endif\n";
  THREE.ShaderChunk['packing'] = "vec3 packNormalToRGB( const in vec3 normal ) {\n  return normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n  return 1.0 - 2.0 * rgb.xyz;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;\nconst vec3 PackFactors = vec3( 256. * 256. * 256., 256. * 256.,  256. );\nconst vec4 UnpackFactors = UnpackDownscale / vec4( PackFactors, 1. );\nconst float ShiftRight8 = 1. / 256.;\nvec4 packDepthToRGBA( const in float v ) {\n	vec4 r = vec4( fract( v * PackFactors ), v );\n	r.yzw -= r.xyz * ShiftRight8;	return r * PackUpscale;\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n	return dot( v, UnpackFactors );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n  return ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float linearClipZ, const in float near, const in float far ) {\n  return linearClipZ * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n  return (( near + viewZ ) * far ) / (( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float invClipZ, const in float near, const in float far ) {\n  return ( near * far ) / ( ( far - near ) * invClipZ - far );\n}\n";
  THREE.ShaderChunk['premultiplied_alpha_fragment'] = "#ifdef PREMULTIPLIED_ALPHA\n	gl_FragColor.rgb *= gl_FragColor.a;\n#endif\n";
  THREE.ShaderChunk['project_vertex'] = "#ifdef USE_SKINNING\n	vec4 mvPosition = modelViewMatrix * skinned;\n#else\n	vec4 mvPosition = modelViewMatrix * vec4( transformed, 1.0 );\n#endif\ngl_Position = projectionMatrix * mvPosition;\n";
  THREE.ShaderChunk['roughnessmap_fragment'] = "float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n	vec4 texelRoughness = texture2D( roughnessMap, vUv );\n	roughnessFactor *= texelRoughness.r;\n#endif\n";
  THREE.ShaderChunk['roughnessmap_pars_fragment'] = "#ifdef USE_ROUGHNESSMAP\n	uniform sampler2D roughnessMap;\n#endif";
  THREE.ShaderChunk['shadowmap_pars_fragment'] = "#ifdef USE_SHADOWMAP\n	#if NUM_DIR_LIGHTS > 0\n		uniform sampler2D directionalShadowMap[ NUM_DIR_LIGHTS ];\n		varying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n	#endif\n	#if NUM_SPOT_LIGHTS > 0\n		uniform sampler2D spotShadowMap[ NUM_SPOT_LIGHTS ];\n		varying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n	#endif\n	#if NUM_POINT_LIGHTS > 0\n		uniform sampler2D pointShadowMap[ NUM_POINT_LIGHTS ];\n		varying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n	#endif\n	float texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n		return step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n	}\n	float texture2DShadowLerp( sampler2D depths, vec2 size, vec2 uv, float compare ) {\n		const vec2 offset = vec2( 0.0, 1.0 );\n		vec2 texelSize = vec2( 1.0 ) / size;\n		vec2 centroidUV = floor( uv * size + 0.5 ) / size;\n		float lb = texture2DCompare( depths, centroidUV + texelSize * offset.xx, compare );\n		float lt = texture2DCompare( depths, centroidUV + texelSize * offset.xy, compare );\n		float rb = texture2DCompare( depths, centroidUV + texelSize * offset.yx, compare );\n		float rt = texture2DCompare( depths, centroidUV + texelSize * offset.yy, compare );\n		vec2 f = fract( uv * size + 0.5 );\n		float a = mix( lb, lt, f.y );\n		float b = mix( rb, rt, f.y );\n		float c = mix( a, b, f.x );\n		return c;\n	}\n	float getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n		shadowCoord.xyz /= shadowCoord.w;\n		shadowCoord.z += shadowBias;\n		bvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\n		bool inFrustum = all( inFrustumVec );\n		bvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n		bool frustumTest = all( frustumTestVec );\n		if ( frustumTest ) {\n		#if defined( SHADOWMAP_TYPE_PCF )\n			vec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n			float dx0 = - texelSize.x * shadowRadius;\n			float dy0 = - texelSize.y * shadowRadius;\n			float dx1 = + texelSize.x * shadowRadius;\n			float dy1 = + texelSize.y * shadowRadius;\n			return (\n				texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n				texture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n				texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n				texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n				texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n				texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n				texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n				texture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n				texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n			) * ( 1.0 / 9.0 );\n		#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n			vec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n			float dx0 = - texelSize.x * shadowRadius;\n			float dy0 = - texelSize.y * shadowRadius;\n			float dx1 = + texelSize.x * shadowRadius;\n			float dy1 = + texelSize.y * shadowRadius;\n			return (\n				texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n				texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n				texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n				texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n				texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy, shadowCoord.z ) +\n				texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n				texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n				texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n				texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n			) * ( 1.0 / 9.0 );\n		#else\n			return texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n		#endif\n		}\n		return 1.0;\n	}\n	vec2 cubeToUV( vec3 v, float texelSizeY ) {\n		vec3 absV = abs( v );\n		float scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n		absV *= scaleToCube;\n		v *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n		vec2 planar = v.xy;\n		float almostATexel = 1.5 * texelSizeY;\n		float almostOne = 1.0 - almostATexel;\n		if ( absV.z >= almostOne ) {\n			if ( v.z > 0.0 )\n				planar.x = 4.0 - v.x;\n		} else if ( absV.x >= almostOne ) {\n			float signX = sign( v.x );\n			planar.x = v.z * signX + 2.0 * signX;\n		} else if ( absV.y >= almostOne ) {\n			float signY = sign( v.y );\n			planar.x = v.x + 2.0 * signY + 2.0;\n			planar.y = v.z * signY - 2.0;\n		}\n		return vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n	}\n	float getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n		vec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n		vec3 lightToPosition = shadowCoord.xyz;\n		vec3 bd3D = normalize( lightToPosition );\n		float dp = ( length( lightToPosition ) - shadowBias ) / 1000.0;\n		#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT )\n			vec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n			return (\n				texture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n				texture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n				texture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n				texture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n				texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n				texture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n				texture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n				texture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n				texture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n			) * ( 1.0 / 9.0 );\n		#else\n			return texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n		#endif\n	}\n#endif\n";
  THREE.ShaderChunk['shadowmap_pars_vertex'] = "#ifdef USE_SHADOWMAP\n	#if NUM_DIR_LIGHTS > 0\n		uniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHTS ];\n		varying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n	#endif\n	#if NUM_SPOT_LIGHTS > 0\n		uniform mat4 spotShadowMatrix[ NUM_SPOT_LIGHTS ];\n		varying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n	#endif\n	#if NUM_POINT_LIGHTS > 0\n		uniform mat4 pointShadowMatrix[ NUM_POINT_LIGHTS ];\n		varying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n	#endif\n#endif\n";
  THREE.ShaderChunk['shadowmap_vertex'] = "#ifdef USE_SHADOWMAP\n	#if NUM_DIR_LIGHTS > 0\n	for ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n		vDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * worldPosition;\n	}\n	#endif\n	#if NUM_SPOT_LIGHTS > 0\n	for ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n		vSpotShadowCoord[ i ] = spotShadowMatrix[ i ] * worldPosition;\n	}\n	#endif\n	#if NUM_POINT_LIGHTS > 0\n	for ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n		vPointShadowCoord[ i ] = pointShadowMatrix[ i ] * worldPosition;\n	}\n	#endif\n#endif\n";
  THREE.ShaderChunk['shadowmask_pars_fragment'] = "float getShadowMask() {\n	float shadow = 1.0;\n	#ifdef USE_SHADOWMAP\n	#if NUM_DIR_LIGHTS > 0\n	DirectionalLight directionalLight;\n	for ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n		directionalLight = directionalLights[ i ];\n		shadow *= bool( directionalLight.shadow ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n	}\n	#endif\n	#if NUM_SPOT_LIGHTS > 0\n	SpotLight spotLight;\n	for ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n		spotLight = spotLights[ i ];\n		shadow *= bool( spotLight.shadow ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n	}\n	#endif\n	#if NUM_POINT_LIGHTS > 0\n	PointLight pointLight;\n	for ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n		pointLight = pointLights[ i ];\n		shadow *= bool( pointLight.shadow ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ] ) : 1.0;\n	}\n	#endif\n	#endif\n	return shadow;\n}\n";
  THREE.ShaderChunk['skinbase_vertex'] = "#ifdef USE_SKINNING\n	mat4 boneMatX = getBoneMatrix( skinIndex.x );\n	mat4 boneMatY = getBoneMatrix( skinIndex.y );\n	mat4 boneMatZ = getBoneMatrix( skinIndex.z );\n	mat4 boneMatW = getBoneMatrix( skinIndex.w );\n#endif";
  THREE.ShaderChunk['skinning_pars_vertex'] = "#ifdef USE_SKINNING\n	uniform mat4 bindMatrix;\n	uniform mat4 bindMatrixInverse;\n	#ifdef BONE_TEXTURE\n		uniform sampler2D boneTexture;\n		uniform int boneTextureWidth;\n		uniform int boneTextureHeight;\n		mat4 getBoneMatrix( const in float i ) {\n			float j = i * 4.0;\n			float x = mod( j, float( boneTextureWidth ) );\n			float y = floor( j / float( boneTextureWidth ) );\n			float dx = 1.0 / float( boneTextureWidth );\n			float dy = 1.0 / float( boneTextureHeight );\n			y = dy * ( y + 0.5 );\n			vec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\n			vec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\n			vec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\n			vec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\n			mat4 bone = mat4( v1, v2, v3, v4 );\n			return bone;\n		}\n	#else\n		uniform mat4 boneMatrices[ MAX_BONES ];\n		mat4 getBoneMatrix( const in float i ) {\n			mat4 bone = boneMatrices[ int(i) ];\n			return bone;\n		}\n	#endif\n#endif\n";
  THREE.ShaderChunk['skinning_vertex'] = "#ifdef USE_SKINNING\n	vec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n	vec4 skinned = vec4( 0.0 );\n	skinned += boneMatX * skinVertex * skinWeight.x;\n	skinned += boneMatY * skinVertex * skinWeight.y;\n	skinned += boneMatZ * skinVertex * skinWeight.z;\n	skinned += boneMatW * skinVertex * skinWeight.w;\n	skinned  = bindMatrixInverse * skinned;\n#endif\n";
  THREE.ShaderChunk['skinnormal_vertex'] = "#ifdef USE_SKINNING\n	mat4 skinMatrix = mat4( 0.0 );\n	skinMatrix += skinWeight.x * boneMatX;\n	skinMatrix += skinWeight.y * boneMatY;\n	skinMatrix += skinWeight.z * boneMatZ;\n	skinMatrix += skinWeight.w * boneMatW;\n	skinMatrix  = bindMatrixInverse * skinMatrix * bindMatrix;\n	objectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n#endif\n";
  THREE.ShaderChunk['specularmap_fragment'] = "float specularStrength;\n#ifdef USE_SPECULARMAP\n	vec4 texelSpecular = texture2D( specularMap, vUv );\n	specularStrength = texelSpecular.r;\n#else\n	specularStrength = 1.0;\n#endif";
  THREE.ShaderChunk['specularmap_pars_fragment'] = "#ifdef USE_SPECULARMAP\n	uniform sampler2D specularMap;\n#endif";
  THREE.ShaderChunk['tonemapping_fragment'] = "#if defined( TONE_MAPPING )\n  gl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif\n";
  THREE.ShaderChunk['tonemapping_pars_fragment'] = "#define saturate(a) clamp( a, 0.0, 1.0 )\nuniform float toneMappingExposure;\nuniform float toneMappingWhitePoint;\nvec3 LinearToneMapping( vec3 color ) {\n  return toneMappingExposure * color;\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n  color *= toneMappingExposure;\n  return saturate( color / ( vec3( 1.0 ) + color ) );\n}\n#define Uncharted2Helper( x ) max( ( ( x * ( 0.15 * x + 0.10 * 0.50 ) + 0.20 * 0.02 ) / ( x * ( 0.15 * x + 0.50 ) + 0.20 * 0.30 ) ) - 0.02 / 0.30, vec3( 0.0 ) )\nvec3 Uncharted2ToneMapping( vec3 color ) {\n  color *= toneMappingExposure;\n  return saturate( Uncharted2Helper( color ) / Uncharted2Helper( vec3( toneMappingWhitePoint ) ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n  color *= toneMappingExposure;\n  color = max( vec3( 0.0 ), color - 0.004 );\n  return pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\n";
  THREE.ShaderChunk['uv2_pars_fragment'] = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n	varying vec2 vUv2;\n#endif";
  THREE.ShaderChunk['uv2_pars_vertex'] = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n	attribute vec2 uv2;\n	varying vec2 vUv2;\n#endif";
  THREE.ShaderChunk['uv2_vertex'] = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n	vUv2 = uv2;\n#endif";
  THREE.ShaderChunk['uv_pars_fragment'] = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n	varying vec2 vUv;\n#endif";
  THREE.ShaderChunk['uv_pars_vertex'] = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n	varying vec2 vUv;\n	uniform vec4 offsetRepeat;\n#endif\n";
  THREE.ShaderChunk['uv_vertex'] = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n	vUv = uv * offsetRepeat.zw + offsetRepeat.xy;\n#endif";
  THREE.ShaderChunk['worldpos_vertex'] = "#if defined( USE_ENVMAP ) || defined( PHONG ) || defined( PHYSICAL ) || defined( LAMBERT ) || defined ( USE_SHADOWMAP )\n	#ifdef USE_SKINNING\n		vec4 worldPosition = modelMatrix * skinned;\n	#else\n		vec4 worldPosition = modelMatrix * vec4( transformed, 1.0 );\n	#endif\n#endif\n";
  THREE.UniformsUtils = {
    merge: function(uniforms) {
      var merged = {};
      for (var u = 0; u < uniforms.length; u++) {
        var tmp = this.clone(uniforms[u]);
        for (var p in tmp) {
          merged[p] = tmp[p];
        }
      }
      return merged;
    },
    clone: function(uniforms_src) {
      var uniforms_dst = {};
      for (var u in uniforms_src) {
        uniforms_dst[u] = {};
        for (var p in uniforms_src[u]) {
          var parameter_src = uniforms_src[u][p];
          if (parameter_src instanceof THREE.Color || parameter_src instanceof THREE.Vector2 || parameter_src instanceof THREE.Vector3 || parameter_src instanceof THREE.Vector4 || parameter_src instanceof THREE.Matrix3 || parameter_src instanceof THREE.Matrix4 || parameter_src instanceof THREE.Texture) {
            uniforms_dst[u][p] = parameter_src.clone();
          } else if (Array.isArray(parameter_src)) {
            uniforms_dst[u][p] = parameter_src.slice();
          } else {
            uniforms_dst[u][p] = parameter_src;
          }
        }
      }
      return uniforms_dst;
    }
  };
  THREE.UniformsLib = {
    common: {
      "diffuse": {value: new THREE.Color(0xeeeeee)},
      "opacity": {value: 1.0},
      "map": {value: null},
      "offsetRepeat": {value: new THREE.Vector4(0, 0, 1, 1)},
      "specularMap": {value: null},
      "alphaMap": {value: null},
      "envMap": {value: null},
      "flipEnvMap": {value: -1},
      "reflectivity": {value: 1.0},
      "refractionRatio": {value: 0.98}
    },
    aomap: {
      "aoMap": {value: null},
      "aoMapIntensity": {value: 1}
    },
    lightmap: {
      "lightMap": {value: null},
      "lightMapIntensity": {value: 1}
    },
    emissivemap: {"emissiveMap": {value: null}},
    bumpmap: {
      "bumpMap": {value: null},
      "bumpScale": {value: 1}
    },
    normalmap: {
      "normalMap": {value: null},
      "normalScale": {value: new THREE.Vector2(1, 1)}
    },
    displacementmap: {
      "displacementMap": {value: null},
      "displacementScale": {value: 1},
      "displacementBias": {value: 0}
    },
    roughnessmap: {"roughnessMap": {value: null}},
    metalnessmap: {"metalnessMap": {value: null}},
    fog: {
      "fogDensity": {value: 0.00025},
      "fogNear": {value: 1},
      "fogFar": {value: 2000},
      "fogColor": {value: new THREE.Color(0xffffff)}
    },
    lights: {
      "ambientLightColor": {value: []},
      "directionalLights": {
        value: [],
        properties: {
          "direction": {},
          "color": {},
          "shadow": {},
          "shadowBias": {},
          "shadowRadius": {},
          "shadowMapSize": {}
        }
      },
      "directionalShadowMap": {value: []},
      "directionalShadowMatrix": {value: []},
      "spotLights": {
        value: [],
        properties: {
          "color": {},
          "position": {},
          "direction": {},
          "distance": {},
          "coneCos": {},
          "penumbraCos": {},
          "decay": {},
          "shadow": {},
          "shadowBias": {},
          "shadowRadius": {},
          "shadowMapSize": {}
        }
      },
      "spotShadowMap": {value: []},
      "spotShadowMatrix": {value: []},
      "pointLights": {
        value: [],
        properties: {
          "color": {},
          "position": {},
          "decay": {},
          "distance": {},
          "shadow": {},
          "shadowBias": {},
          "shadowRadius": {},
          "shadowMapSize": {}
        }
      },
      "pointShadowMap": {value: []},
      "pointShadowMatrix": {value: []},
      "hemisphereLights": {
        value: [],
        properties: {
          "direction": {},
          "skyColor": {},
          "groundColor": {}
        }
      }
    },
    points: {
      "diffuse": {value: new THREE.Color(0xeeeeee)},
      "opacity": {value: 1.0},
      "size": {value: 1.0},
      "scale": {value: 1.0},
      "map": {value: null},
      "offsetRepeat": {value: new THREE.Vector4(0, 0, 1, 1)}
    }
  };
  THREE.ShaderChunk['cube_frag'] = "uniform samplerCube tCube;\nuniform float tFlip;\nvarying vec3 vWorldPosition;\n#include <common>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n	#include <clipping_planes_fragment>\n	gl_FragColor = textureCube( tCube, vec3( tFlip * vWorldPosition.x, vWorldPosition.yz ) );\n	#include <logdepthbuf_fragment>\n}\n";
  THREE.ShaderChunk['cube_vert'] = "varying vec3 vWorldPosition;\n#include <common>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n	vWorldPosition = transformDirection( position, modelMatrix );\n	#include <begin_vertex>\n	#include <project_vertex>\n	#include <logdepthbuf_vertex>\n	#include <clipping_planes_vertex>\n}\n";
  THREE.ShaderChunk['depth_frag'] = "#if DEPTH_PACKING == 3200\n	uniform float opacity;\n#endif\n#include <common>\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n	#include <clipping_planes_fragment>\n	vec4 diffuseColor = vec4( 1.0 );\n	#if DEPTH_PACKING == 3200\n		diffuseColor.a = opacity;\n	#endif\n	#include <map_fragment>\n	#include <alphamap_fragment>\n	#include <alphatest_fragment>\n	#include <logdepthbuf_fragment>\n	#if DEPTH_PACKING == 3200\n		gl_FragColor = vec4( vec3( gl_FragCoord.z ), opacity );\n	#elif DEPTH_PACKING == 3201\n		gl_FragColor = packDepthToRGBA( gl_FragCoord.z );\n	#endif\n}\n";
  THREE.ShaderChunk['depth_vert'] = "#include <common>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n	#include <uv_vertex>\n	#include <skinbase_vertex>\n	#include <begin_vertex>\n	#include <displacementmap_vertex>\n	#include <morphtarget_vertex>\n	#include <skinning_vertex>\n	#include <project_vertex>\n	#include <logdepthbuf_vertex>\n	#include <clipping_planes_vertex>\n}\n";
  THREE.ShaderChunk['distanceRGBA_frag'] = "uniform vec3 lightPos;\nvarying vec4 vWorldPosition;\n#include <common>\n#include <packing>\n#include <clipping_planes_pars_fragment>\nvoid main () {\n	#include <clipping_planes_fragment>\n	gl_FragColor = packDepthToRGBA( length( vWorldPosition.xyz - lightPos.xyz ) / 1000.0 );\n}\n";
  THREE.ShaderChunk['distanceRGBA_vert'] = "varying vec4 vWorldPosition;\n#include <common>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n	#include <skinbase_vertex>\n	#include <begin_vertex>\n	#include <morphtarget_vertex>\n	#include <skinning_vertex>\n	#include <project_vertex>\n	#include <worldpos_vertex>\n	#include <clipping_planes_vertex>\n	vWorldPosition = worldPosition;\n}\n";
  THREE.ShaderChunk['equirect_frag'] = "uniform sampler2D tEquirect;\nuniform float tFlip;\nvarying vec3 vWorldPosition;\n#include <common>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n	#include <clipping_planes_fragment>\n	vec3 direction = normalize( vWorldPosition );\n	vec2 sampleUV;\n	sampleUV.y = saturate( tFlip * direction.y * -0.5 + 0.5 );\n	sampleUV.x = atan( direction.z, direction.x ) * RECIPROCAL_PI2 + 0.5;\n	gl_FragColor = texture2D( tEquirect, sampleUV );\n	#include <logdepthbuf_fragment>\n}\n";
  THREE.ShaderChunk['equirect_vert'] = "varying vec3 vWorldPosition;\n#include <common>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n	vWorldPosition = transformDirection( position, modelMatrix );\n	#include <begin_vertex>\n	#include <project_vertex>\n	#include <logdepthbuf_vertex>\n	#include <clipping_planes_vertex>\n}\n";
  THREE.ShaderChunk['linedashed_frag'] = "uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include <common>\n#include <color_pars_fragment>\n#include <fog_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n	#include <clipping_planes_fragment>\n	if ( mod( vLineDistance, totalSize ) > dashSize ) {\n		discard;\n	}\n	vec3 outgoingLight = vec3( 0.0 );\n	vec4 diffuseColor = vec4( diffuse, opacity );\n	#include <logdepthbuf_fragment>\n	#include <color_fragment>\n	outgoingLight = diffuseColor.rgb;\n	gl_FragColor = vec4( outgoingLight, diffuseColor.a );\n	#include <premultiplied_alpha_fragment>\n	#include <tonemapping_fragment>\n	#include <encodings_fragment>\n	#include <fog_fragment>\n}\n";
  THREE.ShaderChunk['linedashed_vert'] = "uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include <common>\n#include <color_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n	#include <color_vertex>\n	vLineDistance = scale * lineDistance;\n	vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\n	gl_Position = projectionMatrix * mvPosition;\n	#include <logdepthbuf_vertex>\n	#include <clipping_planes_vertex>\n}\n";
  THREE.ShaderChunk['meshbasic_frag'] = "uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n	varying vec3 vNormal;\n#endif\n#include <common>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <aomap_pars_fragment>\n#include <envmap_pars_fragment>\n#include <fog_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n	#include <clipping_planes_fragment>\n	vec4 diffuseColor = vec4( diffuse, opacity );\n	#include <logdepthbuf_fragment>\n	#include <map_fragment>\n	#include <color_fragment>\n	#include <alphamap_fragment>\n	#include <alphatest_fragment>\n	#include <specularmap_fragment>\n	ReflectedLight reflectedLight;\n	reflectedLight.directDiffuse = vec3( 0.0 );\n	reflectedLight.directSpecular = vec3( 0.0 );\n	reflectedLight.indirectDiffuse = diffuseColor.rgb;\n	reflectedLight.indirectSpecular = vec3( 0.0 );\n	#include <aomap_fragment>\n	vec3 outgoingLight = reflectedLight.indirectDiffuse;\n	#include <normal_flip>\n	#include <envmap_fragment>\n	gl_FragColor = vec4( outgoingLight, diffuseColor.a );\n	#include <premultiplied_alpha_fragment>\n	#include <tonemapping_fragment>\n	#include <encodings_fragment>\n	#include <fog_fragment>\n}\n";
  THREE.ShaderChunk['meshbasic_vert'] = "#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <envmap_pars_vertex>\n#include <color_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n	#include <uv_vertex>\n	#include <uv2_vertex>\n	#include <color_vertex>\n	#include <skinbase_vertex>\n	#ifdef USE_ENVMAP\n	#include <beginnormal_vertex>\n	#include <morphnormal_vertex>\n	#include <skinnormal_vertex>\n	#include <defaultnormal_vertex>\n	#endif\n	#include <begin_vertex>\n	#include <morphtarget_vertex>\n	#include <skinning_vertex>\n	#include <project_vertex>\n	#include <logdepthbuf_vertex>\n	#include <worldpos_vertex>\n	#include <clipping_planes_vertex>\n	#include <envmap_vertex>\n}\n";
  THREE.ShaderChunk['meshlambert_frag'] = "uniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\n	varying vec3 vLightBack;\n#endif\n#include <common>\n#include <packing>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <envmap_pars_fragment>\n#include <bsdfs>\n#include <lights_pars>\n#include <fog_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <shadowmask_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n	#include <clipping_planes_fragment>\n	vec4 diffuseColor = vec4( diffuse, opacity );\n	ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n	vec3 totalEmissiveRadiance = emissive;\n	#include <logdepthbuf_fragment>\n	#include <map_fragment>\n	#include <color_fragment>\n	#include <alphamap_fragment>\n	#include <alphatest_fragment>\n	#include <specularmap_fragment>\n	#include <emissivemap_fragment>\n	reflectedLight.indirectDiffuse = getAmbientLightIrradiance( ambientLightColor );\n	#include <lightmap_fragment>\n	reflectedLight.indirectDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb );\n	#ifdef DOUBLE_SIDED\n		reflectedLight.directDiffuse = ( gl_FrontFacing ) ? vLightFront : vLightBack;\n	#else\n		reflectedLight.directDiffuse = vLightFront;\n	#endif\n	reflectedLight.directDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb ) * getShadowMask();\n	#include <aomap_fragment>\n	vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n	#include <normal_flip>\n	#include <envmap_fragment>\n	gl_FragColor = vec4( outgoingLight, diffuseColor.a );\n	#include <premultiplied_alpha_fragment>\n	#include <tonemapping_fragment>\n	#include <encodings_fragment>\n	#include <fog_fragment>\n}\n";
  THREE.ShaderChunk['meshlambert_vert'] = "#define LAMBERT\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\n	varying vec3 vLightBack;\n#endif\n#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <envmap_pars_vertex>\n#include <bsdfs>\n#include <lights_pars>\n#include <color_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n	#include <uv_vertex>\n	#include <uv2_vertex>\n	#include <color_vertex>\n	#include <beginnormal_vertex>\n	#include <morphnormal_vertex>\n	#include <skinbase_vertex>\n	#include <skinnormal_vertex>\n	#include <defaultnormal_vertex>\n	#include <begin_vertex>\n	#include <morphtarget_vertex>\n	#include <skinning_vertex>\n	#include <project_vertex>\n	#include <logdepthbuf_vertex>\n	#include <clipping_planes_vertex>\n	#include <worldpos_vertex>\n	#include <envmap_vertex>\n	#include <lights_lambert_vertex>\n	#include <shadowmap_vertex>\n}\n";
  THREE.ShaderChunk['meshphong_frag'] = "#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include <common>\n#include <packing>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <envmap_pars_fragment>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <lights_pars>\n#include <lights_phong_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n	#include <clipping_planes_fragment>\n	vec4 diffuseColor = vec4( diffuse, opacity );\n	ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n	vec3 totalEmissiveRadiance = emissive;\n	#include <logdepthbuf_fragment>\n	#include <map_fragment>\n	#include <color_fragment>\n	#include <alphamap_fragment>\n	#include <alphatest_fragment>\n	#include <specularmap_fragment>\n	#include <normal_flip>\n	#include <normal_fragment>\n	#include <emissivemap_fragment>\n	#include <lights_phong_fragment>\n	#include <lights_template>\n	#include <aomap_fragment>\n	vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n	#include <envmap_fragment>\n	gl_FragColor = vec4( outgoingLight, diffuseColor.a );\n	#include <premultiplied_alpha_fragment>\n	#include <tonemapping_fragment>\n	#include <encodings_fragment>\n	#include <fog_fragment>\n}\n";
  THREE.ShaderChunk['meshphong_vert'] = "#define PHONG\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n	varying vec3 vNormal;\n#endif\n#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <envmap_pars_vertex>\n#include <color_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n	#include <uv_vertex>\n	#include <uv2_vertex>\n	#include <color_vertex>\n	#include <beginnormal_vertex>\n	#include <morphnormal_vertex>\n	#include <skinbase_vertex>\n	#include <skinnormal_vertex>\n	#include <defaultnormal_vertex>\n#ifndef FLAT_SHADED\n	vNormal = normalize( transformedNormal );\n#endif\n	#include <begin_vertex>\n	#include <displacementmap_vertex>\n	#include <morphtarget_vertex>\n	#include <skinning_vertex>\n	#include <project_vertex>\n	#include <logdepthbuf_vertex>\n	#include <clipping_planes_vertex>\n	vViewPosition = - mvPosition.xyz;\n	#include <worldpos_vertex>\n	#include <envmap_vertex>\n	#include <shadowmap_vertex>\n}\n";
  THREE.ShaderChunk['meshphysical_frag'] = "#define PHYSICAL\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifndef STANDARD\n	uniform float clearCoat;\n	uniform float clearCoatRoughness;\n#endif\nuniform float envMapIntensity;\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n	varying vec3 vNormal;\n#endif\n#include <common>\n#include <packing>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <envmap_pars_fragment>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <cube_uv_reflection_fragment>\n#include <lights_pars>\n#include <lights_physical_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <roughnessmap_pars_fragment>\n#include <metalnessmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n	#include <clipping_planes_fragment>\n	vec4 diffuseColor = vec4( diffuse, opacity );\n	ReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n	vec3 totalEmissiveRadiance = emissive;\n	#include <logdepthbuf_fragment>\n	#include <map_fragment>\n	#include <color_fragment>\n	#include <alphamap_fragment>\n	#include <alphatest_fragment>\n	#include <specularmap_fragment>\n	#include <roughnessmap_fragment>\n	#include <metalnessmap_fragment>\n	#include <normal_flip>\n	#include <normal_fragment>\n	#include <emissivemap_fragment>\n	#include <lights_physical_fragment>\n	#include <lights_template>\n	#include <aomap_fragment>\n	vec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n	gl_FragColor = vec4( outgoingLight, diffuseColor.a );\n	#include <premultiplied_alpha_fragment>\n	#include <tonemapping_fragment>\n	#include <encodings_fragment>\n	#include <fog_fragment>\n}\n";
  THREE.ShaderChunk['meshphysical_vert'] = "#define PHYSICAL\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n	varying vec3 vNormal;\n#endif\n#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <color_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n	#include <uv_vertex>\n	#include <uv2_vertex>\n	#include <color_vertex>\n	#include <beginnormal_vertex>\n	#include <morphnormal_vertex>\n	#include <skinbase_vertex>\n	#include <skinnormal_vertex>\n	#include <defaultnormal_vertex>\n#ifndef FLAT_SHADED\n	vNormal = normalize( transformedNormal );\n#endif\n	#include <begin_vertex>\n	#include <displacementmap_vertex>\n	#include <morphtarget_vertex>\n	#include <skinning_vertex>\n	#include <project_vertex>\n	#include <logdepthbuf_vertex>\n	#include <clipping_planes_vertex>\n	vViewPosition = - mvPosition.xyz;\n	#include <worldpos_vertex>\n	#include <shadowmap_vertex>\n}\n";
  THREE.ShaderChunk['normal_frag'] = "uniform float opacity;\nvarying vec3 vNormal;\n#include <common>\n#include <packing>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n	#include <clipping_planes_fragment>\n	gl_FragColor = vec4( packNormalToRGB( vNormal ), opacity );\n	#include <logdepthbuf_fragment>\n}\n";
  THREE.ShaderChunk['normal_vert'] = "varying vec3 vNormal;\n#include <common>\n#include <morphtarget_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n	vNormal = normalize( normalMatrix * normal );\n	#include <begin_vertex>\n	#include <morphtarget_vertex>\n	#include <project_vertex>\n	#include <logdepthbuf_vertex>\n	#include <clipping_planes_vertex>\n}\n";
  THREE.ShaderChunk['points_frag'] = "uniform vec3 diffuse;\nuniform float opacity;\n#include <common>\n#include <color_pars_fragment>\n#include <map_particle_pars_fragment>\n#include <fog_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n	#include <clipping_planes_fragment>\n	vec3 outgoingLight = vec3( 0.0 );\n	vec4 diffuseColor = vec4( diffuse, opacity );\n	#include <logdepthbuf_fragment>\n	#include <map_particle_fragment>\n	#include <color_fragment>\n	#include <alphatest_fragment>\n	outgoingLight = diffuseColor.rgb;\n	gl_FragColor = vec4( outgoingLight, diffuseColor.a );\n	#include <premultiplied_alpha_fragment>\n	#include <tonemapping_fragment>\n	#include <encodings_fragment>\n	#include <fog_fragment>\n}\n";
  THREE.ShaderChunk['points_vert'] = "uniform float size;\nuniform float scale;\n#include <common>\n#include <color_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n	#include <color_vertex>\n	#include <begin_vertex>\n	#include <project_vertex>\n	#ifdef USE_SIZEATTENUATION\n		gl_PointSize = size * ( scale / - mvPosition.z );\n	#else\n		gl_PointSize = size;\n	#endif\n	#include <logdepthbuf_vertex>\n	#include <clipping_planes_vertex>\n	#include <worldpos_vertex>\n	#include <shadowmap_vertex>\n}\n";
  THREE.ShaderChunk['shadow_frag'] = "uniform float opacity;\n#include <common>\n#include <packing>\n#include <bsdfs>\n#include <lights_pars>\n#include <shadowmap_pars_fragment>\n#include <shadowmask_pars_fragment>\nvoid main() {\n	gl_FragColor = vec4( 0.0, 0.0, 0.0, opacity * ( 1.0  - getShadowMask() ) );\n}\n";
  THREE.ShaderChunk['shadow_vert'] = "#include <shadowmap_pars_vertex>\nvoid main() {\n	#include <begin_vertex>\n	#include <project_vertex>\n	#include <worldpos_vertex>\n	#include <shadowmap_vertex>\n}\n";
  THREE.ShaderLib = {
    'basic': {
      uniforms: THREE.UniformsUtils.merge([THREE.UniformsLib['common'], THREE.UniformsLib['aomap'], THREE.UniformsLib['fog']]),
      vertexShader: THREE.ShaderChunk['meshbasic_vert'],
      fragmentShader: THREE.ShaderChunk['meshbasic_frag']
    },
    'lambert': {
      uniforms: THREE.UniformsUtils.merge([THREE.UniformsLib['common'], THREE.UniformsLib['aomap'], THREE.UniformsLib['lightmap'], THREE.UniformsLib['emissivemap'], THREE.UniformsLib['fog'], THREE.UniformsLib['lights'], {"emissive": {value: new THREE.Color(0x000000)}}]),
      vertexShader: THREE.ShaderChunk['meshlambert_vert'],
      fragmentShader: THREE.ShaderChunk['meshlambert_frag']
    },
    'phong': {
      uniforms: THREE.UniformsUtils.merge([THREE.UniformsLib['common'], THREE.UniformsLib['aomap'], THREE.UniformsLib['lightmap'], THREE.UniformsLib['emissivemap'], THREE.UniformsLib['bumpmap'], THREE.UniformsLib['normalmap'], THREE.UniformsLib['displacementmap'], THREE.UniformsLib['fog'], THREE.UniformsLib['lights'], {
        "emissive": {value: new THREE.Color(0x000000)},
        "specular": {value: new THREE.Color(0x111111)},
        "shininess": {value: 30}
      }]),
      vertexShader: THREE.ShaderChunk['meshphong_vert'],
      fragmentShader: THREE.ShaderChunk['meshphong_frag']
    },
    'standard': {
      uniforms: THREE.UniformsUtils.merge([THREE.UniformsLib['common'], THREE.UniformsLib['aomap'], THREE.UniformsLib['lightmap'], THREE.UniformsLib['emissivemap'], THREE.UniformsLib['bumpmap'], THREE.UniformsLib['normalmap'], THREE.UniformsLib['displacementmap'], THREE.UniformsLib['roughnessmap'], THREE.UniformsLib['metalnessmap'], THREE.UniformsLib['fog'], THREE.UniformsLib['lights'], {
        "emissive": {value: new THREE.Color(0x000000)},
        "roughness": {value: 0.5},
        "metalness": {value: 0},
        "envMapIntensity": {value: 1}
      }]),
      vertexShader: THREE.ShaderChunk['meshphysical_vert'],
      fragmentShader: THREE.ShaderChunk['meshphysical_frag']
    },
    'points': {
      uniforms: THREE.UniformsUtils.merge([THREE.UniformsLib['points'], THREE.UniformsLib['fog']]),
      vertexShader: THREE.ShaderChunk['points_vert'],
      fragmentShader: THREE.ShaderChunk['points_frag']
    },
    'dashed': {
      uniforms: THREE.UniformsUtils.merge([THREE.UniformsLib['common'], THREE.UniformsLib['fog'], {
        "scale": {value: 1},
        "dashSize": {value: 1},
        "totalSize": {value: 2}
      }]),
      vertexShader: THREE.ShaderChunk['linedashed_vert'],
      fragmentShader: THREE.ShaderChunk['linedashed_frag']
    },
    'depth': {
      uniforms: THREE.UniformsUtils.merge([THREE.UniformsLib['common'], THREE.UniformsLib['displacementmap']]),
      vertexShader: THREE.ShaderChunk['depth_vert'],
      fragmentShader: THREE.ShaderChunk['depth_frag']
    },
    'normal': {
      uniforms: {"opacity": {value: 1.0}},
      vertexShader: THREE.ShaderChunk['normal_vert'],
      fragmentShader: THREE.ShaderChunk['normal_frag']
    },
    'cube': {
      uniforms: {
        "tCube": {value: null},
        "tFlip": {value: -1}
      },
      vertexShader: THREE.ShaderChunk['cube_vert'],
      fragmentShader: THREE.ShaderChunk['cube_frag']
    },
    'equirect': {
      uniforms: {
        "tEquirect": {value: null},
        "tFlip": {value: -1}
      },
      vertexShader: THREE.ShaderChunk['equirect_vert'],
      fragmentShader: THREE.ShaderChunk['equirect_frag']
    },
    'distanceRGBA': {
      uniforms: {"lightPos": {value: new THREE.Vector3()}},
      vertexShader: THREE.ShaderChunk['distanceRGBA_vert'],
      fragmentShader: THREE.ShaderChunk['distanceRGBA_frag']
    }
  };
  THREE.ShaderLib['physical'] = {
    uniforms: THREE.UniformsUtils.merge([THREE.ShaderLib['standard'].uniforms, {
      "clearCoat": {value: 0},
      "clearCoatRoughness": {value: 0}
    }]),
    vertexShader: THREE.ShaderChunk['meshphysical_vert'],
    fragmentShader: THREE.ShaderChunk['meshphysical_frag']
  };
  THREE.WebGLRenderer = function(parameters) {
    console.log('THREE.WebGLRenderer', THREE.REVISION);
    parameters = parameters || {};
    var _canvas = parameters.canvas !== undefined ? parameters.canvas : document.createElementNS('http://www.w3.org/1999/xhtml', 'canvas'),
        _context = parameters.context !== undefined ? parameters.context : null,
        _alpha = parameters.alpha !== undefined ? parameters.alpha : false,
        _depth = parameters.depth !== undefined ? parameters.depth : true,
        _stencil = parameters.stencil !== undefined ? parameters.stencil : true,
        _antialias = parameters.antialias !== undefined ? parameters.antialias : false,
        _premultipliedAlpha = parameters.premultipliedAlpha !== undefined ? parameters.premultipliedAlpha : true,
        _preserveDrawingBuffer = parameters.preserveDrawingBuffer !== undefined ? parameters.preserveDrawingBuffer : false;
    var lights = [];
    var opaqueObjects = [];
    var opaqueObjectsLastIndex = -1;
    var transparentObjects = [];
    var transparentObjectsLastIndex = -1;
    var morphInfluences = new Float32Array(8);
    var sprites = [];
    var lensFlares = [];
    this.domElement = _canvas;
    this.context = null;
    this.autoClear = true;
    this.autoClearColor = true;
    this.autoClearDepth = true;
    this.autoClearStencil = true;
    this.sortObjects = true;
    this.clippingPlanes = [];
    this.localClippingEnabled = false;
    this.gammaFactor = 2.0;
    this.gammaInput = false;
    this.gammaOutput = false;
    this.physicallyCorrectLights = false;
    this.toneMapping = THREE.LinearToneMapping;
    this.toneMappingExposure = 1.0;
    this.toneMappingWhitePoint = 1.0;
    this.maxMorphTargets = 8;
    this.maxMorphNormals = 4;
    var _this = this,
        _currentProgram = null,
        _currentRenderTarget = null,
        _currentFramebuffer = null,
        _currentMaterialId = -1,
        _currentGeometryProgram = '',
        _currentCamera = null,
        _currentScissor = new THREE.Vector4(),
        _currentScissorTest = null,
        _currentViewport = new THREE.Vector4(),
        _usedTextureUnits = 0,
        _clearColor = new THREE.Color(0x000000),
        _clearAlpha = 0,
        _width = _canvas.width,
        _height = _canvas.height,
        _pixelRatio = 1,
        _scissor = new THREE.Vector4(0, 0, _width, _height),
        _scissorTest = false,
        _viewport = new THREE.Vector4(0, 0, _width, _height),
        _frustum = new THREE.Frustum(),
        _clipping = new THREE.WebGLClipping(),
        _clippingEnabled = false,
        _localClippingEnabled = false,
        _sphere = new THREE.Sphere(),
        _projScreenMatrix = new THREE.Matrix4(),
        _vector3 = new THREE.Vector3(),
        _lights = {
          hash: '',
          ambient: [0, 0, 0],
          directional: [],
          directionalShadowMap: [],
          directionalShadowMatrix: [],
          spot: [],
          spotShadowMap: [],
          spotShadowMatrix: [],
          point: [],
          pointShadowMap: [],
          pointShadowMatrix: [],
          hemi: [],
          shadows: []
        },
        _infoRender = {
          calls: 0,
          vertices: 0,
          faces: 0,
          points: 0
        };
    this.info = {
      render: _infoRender,
      memory: {
        geometries: 0,
        textures: 0
      },
      programs: null
    };
    var _gl;
    try {
      var attributes = {
        alpha: _alpha,
        depth: _depth,
        stencil: _stencil,
        antialias: _antialias,
        premultipliedAlpha: _premultipliedAlpha,
        preserveDrawingBuffer: _preserveDrawingBuffer
      };
      _gl = _context || _canvas.getContext('webgl', attributes) || _canvas.getContext('experimental-webgl', attributes);
      if (_gl === null) {
        if (_canvas.getContext('webgl') !== null) {
          throw 'Error creating WebGL context with your selected attributes.';
        } else {
          throw 'Error creating WebGL context.';
        }
      }
      if (_gl.getShaderPrecisionFormat === undefined) {
        _gl.getShaderPrecisionFormat = function() {
          return {
            'rangeMin': 1,
            'rangeMax': 1,
            'precision': 1
          };
        };
      }
      _canvas.addEventListener('webglcontextlost', onContextLost, false);
    } catch (error) {
      console.error('THREE.WebGLRenderer: ' + error);
    }
    var extensions = new THREE.WebGLExtensions(_gl);
    extensions.get('WEBGL_depth_texture');
    extensions.get('OES_texture_float');
    extensions.get('OES_texture_float_linear');
    extensions.get('OES_texture_half_float');
    extensions.get('OES_texture_half_float_linear');
    extensions.get('OES_standard_derivatives');
    extensions.get('ANGLE_instanced_arrays');
    if (extensions.get('OES_element_index_uint')) {
      THREE.BufferGeometry.MaxIndex = 4294967296;
    }
    var capabilities = new THREE.WebGLCapabilities(_gl, extensions, parameters);
    var state = new THREE.WebGLState(_gl, extensions, paramThreeToGL);
    var properties = new THREE.WebGLProperties();
    var textures = new THREE.WebGLTextures(_gl, extensions, state, properties, capabilities, paramThreeToGL, this.info);
    var objects = new THREE.WebGLObjects(_gl, properties, this.info);
    var programCache = new THREE.WebGLPrograms(this, capabilities);
    var lightCache = new THREE.WebGLLights();
    this.info.programs = programCache.programs;
    var bufferRenderer = new THREE.WebGLBufferRenderer(_gl, extensions, _infoRender);
    var indexedBufferRenderer = new THREE.WebGLIndexedBufferRenderer(_gl, extensions, _infoRender);
    var backgroundCamera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1);
    var backgroundCamera2 = new THREE.PerspectiveCamera();
    var backgroundPlaneMesh = new THREE.Mesh(new THREE.PlaneBufferGeometry(2, 2), new THREE.MeshBasicMaterial({
      depthTest: false,
      depthWrite: false
    }));
    var backgroundBoxShader = THREE.ShaderLib['cube'];
    var backgroundBoxMesh = new THREE.Mesh(new THREE.BoxBufferGeometry(5, 5, 5), new THREE.ShaderMaterial({
      uniforms: backgroundBoxShader.uniforms,
      vertexShader: backgroundBoxShader.vertexShader,
      fragmentShader: backgroundBoxShader.fragmentShader,
      depthTest: false,
      depthWrite: false,
      side: THREE.BackSide
    }));
    objects.update(backgroundPlaneMesh);
    objects.update(backgroundBoxMesh);
    function getTargetPixelRatio() {
      return _currentRenderTarget === null ? _pixelRatio : 1;
    }
    function glClearColor(r, g, b, a) {
      if (_premultipliedAlpha === true) {
        r *= a;
        g *= a;
        b *= a;
      }
      state.clearColor(r, g, b, a);
    }
    function setDefaultGLState() {
      state.init();
      state.scissor(_currentScissor.copy(_scissor).multiplyScalar(_pixelRatio));
      state.viewport(_currentViewport.copy(_viewport).multiplyScalar(_pixelRatio));
      glClearColor(_clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha);
    }
    function resetGLState() {
      _currentProgram = null;
      _currentCamera = null;
      _currentGeometryProgram = '';
      _currentMaterialId = -1;
      state.reset();
    }
    setDefaultGLState();
    this.context = _gl;
    this.capabilities = capabilities;
    this.extensions = extensions;
    this.properties = properties;
    this.state = state;
    var shadowMap = new THREE.WebGLShadowMap(this, _lights, objects);
    this.shadowMap = shadowMap;
    var spritePlugin = new THREE.SpritePlugin(this, sprites);
    var lensFlarePlugin = new THREE.LensFlarePlugin(this, lensFlares);
    this.getContext = function() {
      return _gl;
    };
    this.getContextAttributes = function() {
      return _gl.getContextAttributes();
    };
    this.forceContextLoss = function() {
      extensions.get('WEBGL_lose_context').loseContext();
    };
    this.getMaxAnisotropy = function() {
      return capabilities.getMaxAnisotropy();
    };
    this.getPrecision = function() {
      return capabilities.precision;
    };
    this.getPixelRatio = function() {
      return _pixelRatio;
    };
    this.setPixelRatio = function(value) {
      if (value === undefined)
        return;
      _pixelRatio = value;
      this.setSize(_viewport.z, _viewport.w, false);
    };
    this.getSize = function() {
      return {
        width: _width,
        height: _height
      };
    };
    this.setSize = function(width, height, updateStyle) {
      _width = width;
      _height = height;
      _canvas.width = width * _pixelRatio;
      _canvas.height = height * _pixelRatio;
      if (updateStyle !== false) {
        _canvas.style.width = width + 'px';
        _canvas.style.height = height + 'px';
      }
      this.setViewport(0, 0, width, height);
    };
    this.setViewport = function(x, y, width, height) {
      state.viewport(_viewport.set(x, y, width, height));
    };
    this.setScissor = function(x, y, width, height) {
      state.scissor(_scissor.set(x, y, width, height));
    };
    this.setScissorTest = function(boolean) {
      state.setScissorTest(_scissorTest = boolean);
    };
    this.getClearColor = function() {
      return _clearColor;
    };
    this.setClearColor = function(color, alpha) {
      _clearColor.set(color);
      _clearAlpha = alpha !== undefined ? alpha : 1;
      glClearColor(_clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha);
    };
    this.getClearAlpha = function() {
      return _clearAlpha;
    };
    this.setClearAlpha = function(alpha) {
      _clearAlpha = alpha;
      glClearColor(_clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha);
    };
    this.clear = function(color, depth, stencil) {
      var bits = 0;
      if (color === undefined || color)
        bits |= _gl.COLOR_BUFFER_BIT;
      if (depth === undefined || depth)
        bits |= _gl.DEPTH_BUFFER_BIT;
      if (stencil === undefined || stencil)
        bits |= _gl.STENCIL_BUFFER_BIT;
      _gl.clear(bits);
    };
    this.clearColor = function() {
      this.clear(true, false, false);
    };
    this.clearDepth = function() {
      this.clear(false, true, false);
    };
    this.clearStencil = function() {
      this.clear(false, false, true);
    };
    this.clearTarget = function(renderTarget, color, depth, stencil) {
      this.setRenderTarget(renderTarget);
      this.clear(color, depth, stencil);
    };
    this.resetGLState = resetGLState;
    this.dispose = function() {
      transparentObjects = [];
      transparentObjectsLastIndex = -1;
      opaqueObjects = [];
      opaqueObjectsLastIndex = -1;
      _canvas.removeEventListener('webglcontextlost', onContextLost, false);
    };
    function onContextLost(event) {
      event.preventDefault();
      resetGLState();
      setDefaultGLState();
      properties.clear();
    }
    function onMaterialDispose(event) {
      var material = event.target;
      material.removeEventListener('dispose', onMaterialDispose);
      deallocateMaterial(material);
    }
    function deallocateMaterial(material) {
      releaseMaterialProgramReference(material);
      properties.delete(material);
    }
    function releaseMaterialProgramReference(material) {
      var programInfo = properties.get(material).program;
      material.program = undefined;
      if (programInfo !== undefined) {
        programCache.releaseProgram(programInfo);
      }
    }
    this.renderBufferImmediate = function(object, program, material) {
      state.initAttributes();
      var buffers = properties.get(object);
      if (object.hasPositions && !buffers.position)
        buffers.position = _gl.createBuffer();
      if (object.hasNormals && !buffers.normal)
        buffers.normal = _gl.createBuffer();
      if (object.hasUvs && !buffers.uv)
        buffers.uv = _gl.createBuffer();
      if (object.hasColors && !buffers.color)
        buffers.color = _gl.createBuffer();
      var attributes = program.getAttributes();
      if (object.hasPositions) {
        _gl.bindBuffer(_gl.ARRAY_BUFFER, buffers.position);
        _gl.bufferData(_gl.ARRAY_BUFFER, object.positionArray, _gl.DYNAMIC_DRAW);
        state.enableAttribute(attributes.position);
        _gl.vertexAttribPointer(attributes.position, 3, _gl.FLOAT, false, 0, 0);
      }
      if (object.hasNormals) {
        _gl.bindBuffer(_gl.ARRAY_BUFFER, buffers.normal);
        if (material.type !== 'MeshPhongMaterial' && material.type !== 'MeshStandardMaterial' && material.type !== 'MeshPhysicalMaterial' && material.shading === THREE.FlatShading) {
          for (var i = 0,
              l = object.count * 3; i < l; i += 9) {
            var array = object.normalArray;
            var nx = (array[i + 0] + array[i + 3] + array[i + 6]) / 3;
            var ny = (array[i + 1] + array[i + 4] + array[i + 7]) / 3;
            var nz = (array[i + 2] + array[i + 5] + array[i + 8]) / 3;
            array[i + 0] = nx;
            array[i + 1] = ny;
            array[i + 2] = nz;
            array[i + 3] = nx;
            array[i + 4] = ny;
            array[i + 5] = nz;
            array[i + 6] = nx;
            array[i + 7] = ny;
            array[i + 8] = nz;
          }
        }
        _gl.bufferData(_gl.ARRAY_BUFFER, object.normalArray, _gl.DYNAMIC_DRAW);
        state.enableAttribute(attributes.normal);
        _gl.vertexAttribPointer(attributes.normal, 3, _gl.FLOAT, false, 0, 0);
      }
      if (object.hasUvs && material.map) {
        _gl.bindBuffer(_gl.ARRAY_BUFFER, buffers.uv);
        _gl.bufferData(_gl.ARRAY_BUFFER, object.uvArray, _gl.DYNAMIC_DRAW);
        state.enableAttribute(attributes.uv);
        _gl.vertexAttribPointer(attributes.uv, 2, _gl.FLOAT, false, 0, 0);
      }
      if (object.hasColors && material.vertexColors !== THREE.NoColors) {
        _gl.bindBuffer(_gl.ARRAY_BUFFER, buffers.color);
        _gl.bufferData(_gl.ARRAY_BUFFER, object.colorArray, _gl.DYNAMIC_DRAW);
        state.enableAttribute(attributes.color);
        _gl.vertexAttribPointer(attributes.color, 3, _gl.FLOAT, false, 0, 0);
      }
      state.disableUnusedAttributes();
      _gl.drawArrays(_gl.TRIANGLES, 0, object.count);
      object.count = 0;
    };
    this.renderBufferDirect = function(camera, fog, geometry, material, object, group) {
      setMaterial(material);
      var program = setProgram(camera, fog, material, object);
      var updateBuffers = false;
      var geometryProgram = geometry.id + '_' + program.id + '_' + material.wireframe;
      if (geometryProgram !== _currentGeometryProgram) {
        _currentGeometryProgram = geometryProgram;
        updateBuffers = true;
      }
      var morphTargetInfluences = object.morphTargetInfluences;
      if (morphTargetInfluences !== undefined) {
        var activeInfluences = [];
        for (var i = 0,
            l = morphTargetInfluences.length; i < l; i++) {
          var influence = morphTargetInfluences[i];
          activeInfluences.push([influence, i]);
        }
        activeInfluences.sort(absNumericalSort);
        if (activeInfluences.length > 8) {
          activeInfluences.length = 8;
        }
        var morphAttributes = geometry.morphAttributes;
        for (var i = 0,
            l = activeInfluences.length; i < l; i++) {
          var influence = activeInfluences[i];
          morphInfluences[i] = influence[0];
          if (influence[0] !== 0) {
            var index = influence[1];
            if (material.morphTargets === true && morphAttributes.position)
              geometry.addAttribute('morphTarget' + i, morphAttributes.position[index]);
            if (material.morphNormals === true && morphAttributes.normal)
              geometry.addAttribute('morphNormal' + i, morphAttributes.normal[index]);
          } else {
            if (material.morphTargets === true)
              geometry.removeAttribute('morphTarget' + i);
            if (material.morphNormals === true)
              geometry.removeAttribute('morphNormal' + i);
          }
        }
        program.getUniforms().setValue(_gl, 'morphTargetInfluences', morphInfluences);
        updateBuffers = true;
      }
      var index = geometry.index;
      var position = geometry.attributes.position;
      if (material.wireframe === true) {
        index = objects.getWireframeAttribute(geometry);
      }
      var renderer;
      if (index !== null) {
        renderer = indexedBufferRenderer;
        renderer.setIndex(index);
      } else {
        renderer = bufferRenderer;
      }
      if (updateBuffers) {
        setupVertexAttributes(material, program, geometry);
        if (index !== null) {
          _gl.bindBuffer(_gl.ELEMENT_ARRAY_BUFFER, objects.getAttributeBuffer(index));
        }
      }
      var dataStart = 0;
      var dataCount = Infinity;
      if (index !== null) {
        dataCount = index.count;
      } else if (position !== undefined) {
        dataCount = position.count;
      }
      var rangeStart = geometry.drawRange.start;
      var rangeCount = geometry.drawRange.count;
      var groupStart = group !== null ? group.start : 0;
      var groupCount = group !== null ? group.count : Infinity;
      var drawStart = Math.max(dataStart, rangeStart, groupStart);
      var drawEnd = Math.min(dataStart + dataCount, rangeStart + rangeCount, groupStart + groupCount) - 1;
      var drawCount = Math.max(0, drawEnd - drawStart + 1);
      if (object instanceof THREE.Mesh) {
        if (material.wireframe === true) {
          state.setLineWidth(material.wireframeLinewidth * getTargetPixelRatio());
          renderer.setMode(_gl.LINES);
        } else {
          switch (object.drawMode) {
            case THREE.TrianglesDrawMode:
              renderer.setMode(_gl.TRIANGLES);
              break;
            case THREE.TriangleStripDrawMode:
              renderer.setMode(_gl.TRIANGLE_STRIP);
              break;
            case THREE.TriangleFanDrawMode:
              renderer.setMode(_gl.TRIANGLE_FAN);
              break;
          }
        }
      } else if (object instanceof THREE.Line) {
        var lineWidth = material.linewidth;
        if (lineWidth === undefined)
          lineWidth = 1;
        state.setLineWidth(lineWidth * getTargetPixelRatio());
        if (object instanceof THREE.LineSegments) {
          renderer.setMode(_gl.LINES);
        } else {
          renderer.setMode(_gl.LINE_STRIP);
        }
      } else if (object instanceof THREE.Points) {
        renderer.setMode(_gl.POINTS);
      }
      if (geometry instanceof THREE.InstancedBufferGeometry) {
        if (geometry.maxInstancedCount > 0) {
          renderer.renderInstances(geometry, drawStart, drawCount);
        }
      } else {
        renderer.render(drawStart, drawCount);
      }
    };
    function setupVertexAttributes(material, program, geometry, startIndex) {
      var extension;
      if (geometry instanceof THREE.InstancedBufferGeometry) {
        extension = extensions.get('ANGLE_instanced_arrays');
        if (extension === null) {
          console.error('THREE.WebGLRenderer.setupVertexAttributes: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.');
          return;
        }
      }
      if (startIndex === undefined)
        startIndex = 0;
      state.initAttributes();
      var geometryAttributes = geometry.attributes;
      var programAttributes = program.getAttributes();
      var materialDefaultAttributeValues = material.defaultAttributeValues;
      for (var name in programAttributes) {
        var programAttribute = programAttributes[name];
        if (programAttribute >= 0) {
          var geometryAttribute = geometryAttributes[name];
          if (geometryAttribute !== undefined) {
            var type = _gl.FLOAT;
            var array = geometryAttribute.array;
            var normalized = geometryAttribute.normalized;
            if (array instanceof Float32Array) {
              type = _gl.FLOAT;
            } else if (array instanceof Float64Array) {
              console.warn("Unsupported data buffer format: Float64Array");
            } else if (array instanceof Uint16Array) {
              type = _gl.UNSIGNED_SHORT;
            } else if (array instanceof Int16Array) {
              type = _gl.SHORT;
            } else if (array instanceof Uint32Array) {
              type = _gl.UNSIGNED_INT;
            } else if (array instanceof Int32Array) {
              type = _gl.INT;
            } else if (array instanceof Int8Array) {
              type = _gl.BYTE;
            } else if (array instanceof Uint8Array) {
              type = _gl.UNSIGNED_BYTE;
            }
            var size = geometryAttribute.itemSize;
            var buffer = objects.getAttributeBuffer(geometryAttribute);
            if (geometryAttribute instanceof THREE.InterleavedBufferAttribute) {
              var data = geometryAttribute.data;
              var stride = data.stride;
              var offset = geometryAttribute.offset;
              if (data instanceof THREE.InstancedInterleavedBuffer) {
                state.enableAttributeAndDivisor(programAttribute, data.meshPerAttribute, extension);
                if (geometry.maxInstancedCount === undefined) {
                  geometry.maxInstancedCount = data.meshPerAttribute * data.count;
                }
              } else {
                state.enableAttribute(programAttribute);
              }
              _gl.bindBuffer(_gl.ARRAY_BUFFER, buffer);
              _gl.vertexAttribPointer(programAttribute, size, type, normalized, stride * data.array.BYTES_PER_ELEMENT, (startIndex * stride + offset) * data.array.BYTES_PER_ELEMENT);
            } else {
              if (geometryAttribute instanceof THREE.InstancedBufferAttribute) {
                state.enableAttributeAndDivisor(programAttribute, geometryAttribute.meshPerAttribute, extension);
                if (geometry.maxInstancedCount === undefined) {
                  geometry.maxInstancedCount = geometryAttribute.meshPerAttribute * geometryAttribute.count;
                }
              } else {
                state.enableAttribute(programAttribute);
              }
              _gl.bindBuffer(_gl.ARRAY_BUFFER, buffer);
              _gl.vertexAttribPointer(programAttribute, size, type, normalized, 0, startIndex * size * geometryAttribute.array.BYTES_PER_ELEMENT);
            }
          } else if (materialDefaultAttributeValues !== undefined) {
            var value = materialDefaultAttributeValues[name];
            if (value !== undefined) {
              switch (value.length) {
                case 2:
                  _gl.vertexAttrib2fv(programAttribute, value);
                  break;
                case 3:
                  _gl.vertexAttrib3fv(programAttribute, value);
                  break;
                case 4:
                  _gl.vertexAttrib4fv(programAttribute, value);
                  break;
                default:
                  _gl.vertexAttrib1fv(programAttribute, value);
              }
            }
          }
        }
      }
      state.disableUnusedAttributes();
    }
    function absNumericalSort(a, b) {
      return Math.abs(b[0]) - Math.abs(a[0]);
    }
    function painterSortStable(a, b) {
      if (a.object.renderOrder !== b.object.renderOrder) {
        return a.object.renderOrder - b.object.renderOrder;
      } else if (a.material.id !== b.material.id) {
        return a.material.id - b.material.id;
      } else if (a.z !== b.z) {
        return a.z - b.z;
      } else {
        return a.id - b.id;
      }
    }
    function reversePainterSortStable(a, b) {
      if (a.object.renderOrder !== b.object.renderOrder) {
        return a.object.renderOrder - b.object.renderOrder;
      }
      if (a.z !== b.z) {
        return b.z - a.z;
      } else {
        return a.id - b.id;
      }
    }
    this.render = function(scene, camera, renderTarget, forceClear) {
      if (camera instanceof THREE.Camera === false) {
        console.error('THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.');
        return;
      }
      var fog = scene.fog;
      _currentGeometryProgram = '';
      _currentMaterialId = -1;
      _currentCamera = null;
      if (scene.autoUpdate === true)
        scene.updateMatrixWorld();
      if (camera.parent === null)
        camera.updateMatrixWorld();
      camera.matrixWorldInverse.getInverse(camera.matrixWorld);
      _projScreenMatrix.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse);
      _frustum.setFromMatrix(_projScreenMatrix);
      lights.length = 0;
      opaqueObjectsLastIndex = -1;
      transparentObjectsLastIndex = -1;
      sprites.length = 0;
      lensFlares.length = 0;
      _localClippingEnabled = this.localClippingEnabled;
      _clippingEnabled = _clipping.init(this.clippingPlanes, _localClippingEnabled, camera);
      projectObject(scene, camera);
      opaqueObjects.length = opaqueObjectsLastIndex + 1;
      transparentObjects.length = transparentObjectsLastIndex + 1;
      if (_this.sortObjects === true) {
        opaqueObjects.sort(painterSortStable);
        transparentObjects.sort(reversePainterSortStable);
      }
      if (_clippingEnabled)
        _clipping.beginShadows();
      setupShadows(lights);
      shadowMap.render(scene, camera);
      setupLights(lights, camera);
      if (_clippingEnabled)
        _clipping.endShadows();
      _infoRender.calls = 0;
      _infoRender.vertices = 0;
      _infoRender.faces = 0;
      _infoRender.points = 0;
      if (renderTarget === undefined) {
        renderTarget = null;
      }
      this.setRenderTarget(renderTarget);
      var background = scene.background;
      if (background === null) {
        glClearColor(_clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha);
      } else if (background instanceof THREE.Color) {
        glClearColor(background.r, background.g, background.b, 1);
      }
      if (this.autoClear || forceClear) {
        this.clear(this.autoClearColor, this.autoClearDepth, this.autoClearStencil);
      }
      if (background instanceof THREE.CubeTexture) {
        backgroundCamera2.projectionMatrix.copy(camera.projectionMatrix);
        backgroundCamera2.matrixWorld.extractRotation(camera.matrixWorld);
        backgroundCamera2.matrixWorldInverse.getInverse(backgroundCamera2.matrixWorld);
        backgroundBoxMesh.material.uniforms["tCube"].value = background;
        backgroundBoxMesh.modelViewMatrix.multiplyMatrices(backgroundCamera2.matrixWorldInverse, backgroundBoxMesh.matrixWorld);
        _this.renderBufferDirect(backgroundCamera2, null, backgroundBoxMesh.geometry, backgroundBoxMesh.material, backgroundBoxMesh, null);
      } else if (background instanceof THREE.Texture) {
        backgroundPlaneMesh.material.map = background;
        _this.renderBufferDirect(backgroundCamera, null, backgroundPlaneMesh.geometry, backgroundPlaneMesh.material, backgroundPlaneMesh, null);
      }
      if (scene.overrideMaterial) {
        var overrideMaterial = scene.overrideMaterial;
        renderObjects(opaqueObjects, camera, fog, overrideMaterial);
        renderObjects(transparentObjects, camera, fog, overrideMaterial);
      } else {
        state.setBlending(THREE.NoBlending);
        renderObjects(opaqueObjects, camera, fog);
        renderObjects(transparentObjects, camera, fog);
      }
      spritePlugin.render(scene, camera);
      lensFlarePlugin.render(scene, camera, _currentViewport);
      if (renderTarget) {
        textures.updateRenderTargetMipmap(renderTarget);
      }
      state.setDepthTest(true);
      state.setDepthWrite(true);
      state.setColorWrite(true);
    };
    function pushRenderItem(object, geometry, material, z, group) {
      var array,
          index;
      if (material.transparent) {
        array = transparentObjects;
        index = ++transparentObjectsLastIndex;
      } else {
        array = opaqueObjects;
        index = ++opaqueObjectsLastIndex;
      }
      var renderItem = array[index];
      if (renderItem !== undefined) {
        renderItem.id = object.id;
        renderItem.object = object;
        renderItem.geometry = geometry;
        renderItem.material = material;
        renderItem.z = _vector3.z;
        renderItem.group = group;
      } else {
        renderItem = {
          id: object.id,
          object: object,
          geometry: geometry,
          material: material,
          z: _vector3.z,
          group: group
        };
        array.push(renderItem);
      }
    }
    function isObjectViewable(object) {
      var geometry = object.geometry;
      if (geometry.boundingSphere === null)
        geometry.computeBoundingSphere();
      _sphere.copy(geometry.boundingSphere).applyMatrix4(object.matrixWorld);
      return isSphereViewable(_sphere);
    }
    function isSpriteViewable(sprite) {
      _sphere.center.set(0, 0, 0);
      _sphere.radius = 0.7071067811865476;
      _sphere.applyMatrix4(sprite.matrixWorld);
      return isSphereViewable(_sphere);
    }
    function isSphereViewable(sphere) {
      if (!_frustum.intersectsSphere(sphere))
        return false;
      var numPlanes = _clipping.numPlanes;
      if (numPlanes === 0)
        return true;
      var planes = _this.clippingPlanes,
          center = sphere.center,
          negRad = -sphere.radius,
          i = 0;
      do {
        if (planes[i].distanceToPoint(center) < negRad)
          return false;
      } while (++i !== numPlanes);
      return true;
    }
    function projectObject(object, camera) {
      if (object.visible === false)
        return;
      if (object.layers.test(camera.layers)) {
        if (object instanceof THREE.Light) {
          lights.push(object);
        } else if (object instanceof THREE.Sprite) {
          if (object.frustumCulled === false || isSpriteViewable(object) === true) {
            sprites.push(object);
          }
        } else if (object instanceof THREE.LensFlare) {
          lensFlares.push(object);
        } else if (object instanceof THREE.ImmediateRenderObject) {
          if (_this.sortObjects === true) {
            _vector3.setFromMatrixPosition(object.matrixWorld);
            _vector3.applyProjection(_projScreenMatrix);
          }
          pushRenderItem(object, null, object.material, _vector3.z, null);
        } else if (object instanceof THREE.Mesh || object instanceof THREE.Line || object instanceof THREE.Points) {
          if (object instanceof THREE.SkinnedMesh) {
            object.skeleton.update();
          }
          if (object.frustumCulled === false || isObjectViewable(object) === true) {
            var material = object.material;
            if (material.visible === true) {
              if (_this.sortObjects === true) {
                _vector3.setFromMatrixPosition(object.matrixWorld);
                _vector3.applyProjection(_projScreenMatrix);
              }
              var geometry = objects.update(object);
              if (material instanceof THREE.MultiMaterial) {
                var groups = geometry.groups;
                var materials = material.materials;
                for (var i = 0,
                    l = groups.length; i < l; i++) {
                  var group = groups[i];
                  var groupMaterial = materials[group.materialIndex];
                  if (groupMaterial.visible === true) {
                    pushRenderItem(object, geometry, groupMaterial, _vector3.z, group);
                  }
                }
              } else {
                pushRenderItem(object, geometry, material, _vector3.z, null);
              }
            }
          }
        }
      }
      var children = object.children;
      for (var i = 0,
          l = children.length; i < l; i++) {
        projectObject(children[i], camera);
      }
    }
    function renderObjects(renderList, camera, fog, overrideMaterial) {
      for (var i = 0,
          l = renderList.length; i < l; i++) {
        var renderItem = renderList[i];
        var object = renderItem.object;
        var geometry = renderItem.geometry;
        var material = overrideMaterial === undefined ? renderItem.material : overrideMaterial;
        var group = renderItem.group;
        object.modelViewMatrix.multiplyMatrices(camera.matrixWorldInverse, object.matrixWorld);
        object.normalMatrix.getNormalMatrix(object.modelViewMatrix);
        if (object instanceof THREE.ImmediateRenderObject) {
          setMaterial(material);
          var program = setProgram(camera, fog, material, object);
          _currentGeometryProgram = '';
          object.render(function(object) {
            _this.renderBufferImmediate(object, program, material);
          });
        } else {
          _this.renderBufferDirect(camera, fog, geometry, material, object, group);
        }
      }
    }
    function initMaterial(material, fog, object) {
      var materialProperties = properties.get(material);
      var parameters = programCache.getParameters(material, _lights, fog, _clipping.numPlanes, object);
      var code = programCache.getProgramCode(material, parameters);
      var program = materialProperties.program;
      var programChange = true;
      if (program === undefined) {
        material.addEventListener('dispose', onMaterialDispose);
      } else if (program.code !== code) {
        releaseMaterialProgramReference(material);
      } else if (parameters.shaderID !== undefined) {
        return;
      } else {
        programChange = false;
      }
      if (programChange) {
        if (parameters.shaderID) {
          var shader = THREE.ShaderLib[parameters.shaderID];
          materialProperties.__webglShader = {
            name: material.type,
            uniforms: THREE.UniformsUtils.clone(shader.uniforms),
            vertexShader: shader.vertexShader,
            fragmentShader: shader.fragmentShader
          };
        } else {
          materialProperties.__webglShader = {
            name: material.type,
            uniforms: material.uniforms,
            vertexShader: material.vertexShader,
            fragmentShader: material.fragmentShader
          };
        }
        material.__webglShader = materialProperties.__webglShader;
        program = programCache.acquireProgram(material, parameters, code);
        materialProperties.program = program;
        material.program = program;
      }
      var attributes = program.getAttributes();
      if (material.morphTargets) {
        material.numSupportedMorphTargets = 0;
        for (var i = 0; i < _this.maxMorphTargets; i++) {
          if (attributes['morphTarget' + i] >= 0) {
            material.numSupportedMorphTargets++;
          }
        }
      }
      if (material.morphNormals) {
        material.numSupportedMorphNormals = 0;
        for (var i = 0; i < _this.maxMorphNormals; i++) {
          if (attributes['morphNormal' + i] >= 0) {
            material.numSupportedMorphNormals++;
          }
        }
      }
      var uniforms = materialProperties.__webglShader.uniforms;
      if (!(material instanceof THREE.ShaderMaterial) && !(material instanceof THREE.RawShaderMaterial) || material.clipping === true) {
        materialProperties.numClippingPlanes = _clipping.numPlanes;
        uniforms.clippingPlanes = _clipping.uniform;
      }
      if (material.lights) {
        materialProperties.lightsHash = _lights.hash;
        uniforms.ambientLightColor.value = _lights.ambient;
        uniforms.directionalLights.value = _lights.directional;
        uniforms.spotLights.value = _lights.spot;
        uniforms.pointLights.value = _lights.point;
        uniforms.hemisphereLights.value = _lights.hemi;
        uniforms.directionalShadowMap.value = _lights.directionalShadowMap;
        uniforms.directionalShadowMatrix.value = _lights.directionalShadowMatrix;
        uniforms.spotShadowMap.value = _lights.spotShadowMap;
        uniforms.spotShadowMatrix.value = _lights.spotShadowMatrix;
        uniforms.pointShadowMap.value = _lights.pointShadowMap;
        uniforms.pointShadowMatrix.value = _lights.pointShadowMatrix;
      }
      var progUniforms = materialProperties.program.getUniforms(),
          uniformsList = THREE.WebGLUniforms.seqWithValue(progUniforms.seq, uniforms);
      materialProperties.uniformsList = uniformsList;
      materialProperties.dynamicUniforms = THREE.WebGLUniforms.splitDynamic(uniformsList, uniforms);
    }
    function setMaterial(material) {
      if (material.side !== THREE.DoubleSide)
        state.enable(_gl.CULL_FACE);
      else
        state.disable(_gl.CULL_FACE);
      state.setFlipSided(material.side === THREE.BackSide);
      if (material.transparent === true) {
        state.setBlending(material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.premultipliedAlpha);
      } else {
        state.setBlending(THREE.NoBlending);
      }
      state.setDepthFunc(material.depthFunc);
      state.setDepthTest(material.depthTest);
      state.setDepthWrite(material.depthWrite);
      state.setColorWrite(material.colorWrite);
      state.setPolygonOffset(material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits);
    }
    function setProgram(camera, fog, material, object) {
      _usedTextureUnits = 0;
      var materialProperties = properties.get(material);
      if (_clippingEnabled) {
        if (_localClippingEnabled || camera !== _currentCamera) {
          var useCache = camera === _currentCamera && material.id === _currentMaterialId;
          _clipping.setState(material.clippingPlanes, material.clipShadows, camera, materialProperties, useCache);
        }
        if (materialProperties.numClippingPlanes !== undefined && materialProperties.numClippingPlanes !== _clipping.numPlanes) {
          material.needsUpdate = true;
        }
      }
      if (materialProperties.program === undefined) {
        material.needsUpdate = true;
      }
      if (materialProperties.lightsHash !== undefined && materialProperties.lightsHash !== _lights.hash) {
        material.needsUpdate = true;
      }
      if (material.needsUpdate) {
        initMaterial(material, fog, object);
        material.needsUpdate = false;
      }
      var refreshProgram = false;
      var refreshMaterial = false;
      var refreshLights = false;
      var program = materialProperties.program,
          p_uniforms = program.getUniforms(),
          m_uniforms = materialProperties.__webglShader.uniforms;
      if (program.id !== _currentProgram) {
        _gl.useProgram(program.program);
        _currentProgram = program.id;
        refreshProgram = true;
        refreshMaterial = true;
        refreshLights = true;
      }
      if (material.id !== _currentMaterialId) {
        _currentMaterialId = material.id;
        refreshMaterial = true;
      }
      if (refreshProgram || camera !== _currentCamera) {
        p_uniforms.set(_gl, camera, 'projectionMatrix');
        if (capabilities.logarithmicDepthBuffer) {
          p_uniforms.setValue(_gl, 'logDepthBufFC', 2.0 / (Math.log(camera.far + 1.0) / Math.LN2));
        }
        if (camera !== _currentCamera) {
          _currentCamera = camera;
          refreshMaterial = true;
          refreshLights = true;
        }
        if (material instanceof THREE.ShaderMaterial || material instanceof THREE.MeshPhongMaterial || material instanceof THREE.MeshStandardMaterial || material.envMap) {
          var uCamPos = p_uniforms.map.cameraPosition;
          if (uCamPos !== undefined) {
            uCamPos.setValue(_gl, _vector3.setFromMatrixPosition(camera.matrixWorld));
          }
        }
        if (material instanceof THREE.MeshPhongMaterial || material instanceof THREE.MeshLambertMaterial || material instanceof THREE.MeshBasicMaterial || material instanceof THREE.MeshStandardMaterial || material instanceof THREE.ShaderMaterial || material.skinning) {
          p_uniforms.setValue(_gl, 'viewMatrix', camera.matrixWorldInverse);
        }
        p_uniforms.set(_gl, _this, 'toneMappingExposure');
        p_uniforms.set(_gl, _this, 'toneMappingWhitePoint');
      }
      if (material.skinning) {
        p_uniforms.setOptional(_gl, object, 'bindMatrix');
        p_uniforms.setOptional(_gl, object, 'bindMatrixInverse');
        var skeleton = object.skeleton;
        if (skeleton) {
          if (capabilities.floatVertexTextures && skeleton.useVertexTexture) {
            p_uniforms.set(_gl, skeleton, 'boneTexture');
            p_uniforms.set(_gl, skeleton, 'boneTextureWidth');
            p_uniforms.set(_gl, skeleton, 'boneTextureHeight');
          } else {
            p_uniforms.setOptional(_gl, skeleton, 'boneMatrices');
          }
        }
      }
      if (refreshMaterial) {
        if (material.lights) {
          markUniformsLightsNeedsUpdate(m_uniforms, refreshLights);
        }
        if (fog && material.fog) {
          refreshUniformsFog(m_uniforms, fog);
        }
        if (material instanceof THREE.MeshBasicMaterial || material instanceof THREE.MeshLambertMaterial || material instanceof THREE.MeshPhongMaterial || material instanceof THREE.MeshStandardMaterial || material instanceof THREE.MeshDepthMaterial) {
          refreshUniformsCommon(m_uniforms, material);
        }
        if (material instanceof THREE.LineBasicMaterial) {
          refreshUniformsLine(m_uniforms, material);
        } else if (material instanceof THREE.LineDashedMaterial) {
          refreshUniformsLine(m_uniforms, material);
          refreshUniformsDash(m_uniforms, material);
        } else if (material instanceof THREE.PointsMaterial) {
          refreshUniformsPoints(m_uniforms, material);
        } else if (material instanceof THREE.MeshLambertMaterial) {
          refreshUniformsLambert(m_uniforms, material);
        } else if (material instanceof THREE.MeshPhongMaterial) {
          refreshUniformsPhong(m_uniforms, material);
        } else if (material instanceof THREE.MeshPhysicalMaterial) {
          refreshUniformsPhysical(m_uniforms, material);
        } else if (material instanceof THREE.MeshStandardMaterial) {
          refreshUniformsStandard(m_uniforms, material);
        } else if (material instanceof THREE.MeshDepthMaterial) {
          if (material.displacementMap) {
            m_uniforms.displacementMap.value = material.displacementMap;
            m_uniforms.displacementScale.value = material.displacementScale;
            m_uniforms.displacementBias.value = material.displacementBias;
          }
        } else if (material instanceof THREE.MeshNormalMaterial) {
          m_uniforms.opacity.value = material.opacity;
        }
        THREE.WebGLUniforms.upload(_gl, materialProperties.uniformsList, m_uniforms, _this);
      }
      p_uniforms.set(_gl, object, 'modelViewMatrix');
      p_uniforms.set(_gl, object, 'normalMatrix');
      p_uniforms.setValue(_gl, 'modelMatrix', object.matrixWorld);
      var dynUniforms = materialProperties.dynamicUniforms;
      if (dynUniforms !== null) {
        THREE.WebGLUniforms.evalDynamic(dynUniforms, m_uniforms, object, camera);
        THREE.WebGLUniforms.upload(_gl, dynUniforms, m_uniforms, _this);
      }
      return program;
    }
    function refreshUniformsCommon(uniforms, material) {
      uniforms.opacity.value = material.opacity;
      uniforms.diffuse.value = material.color;
      if (material.emissive) {
        uniforms.emissive.value.copy(material.emissive).multiplyScalar(material.emissiveIntensity);
      }
      uniforms.map.value = material.map;
      uniforms.specularMap.value = material.specularMap;
      uniforms.alphaMap.value = material.alphaMap;
      if (material.aoMap) {
        uniforms.aoMap.value = material.aoMap;
        uniforms.aoMapIntensity.value = material.aoMapIntensity;
      }
      var uvScaleMap;
      if (material.map) {
        uvScaleMap = material.map;
      } else if (material.specularMap) {
        uvScaleMap = material.specularMap;
      } else if (material.displacementMap) {
        uvScaleMap = material.displacementMap;
      } else if (material.normalMap) {
        uvScaleMap = material.normalMap;
      } else if (material.bumpMap) {
        uvScaleMap = material.bumpMap;
      } else if (material.roughnessMap) {
        uvScaleMap = material.roughnessMap;
      } else if (material.metalnessMap) {
        uvScaleMap = material.metalnessMap;
      } else if (material.alphaMap) {
        uvScaleMap = material.alphaMap;
      } else if (material.emissiveMap) {
        uvScaleMap = material.emissiveMap;
      }
      if (uvScaleMap !== undefined) {
        if (uvScaleMap instanceof THREE.WebGLRenderTarget) {
          uvScaleMap = uvScaleMap.texture;
        }
        var offset = uvScaleMap.offset;
        var repeat = uvScaleMap.repeat;
        uniforms.offsetRepeat.value.set(offset.x, offset.y, repeat.x, repeat.y);
      }
      uniforms.envMap.value = material.envMap;
      uniforms.flipEnvMap.value = (!(material.envMap instanceof THREE.CubeTexture)) ? 1 : -1;
      uniforms.reflectivity.value = material.reflectivity;
      uniforms.refractionRatio.value = material.refractionRatio;
    }
    function refreshUniformsLine(uniforms, material) {
      uniforms.diffuse.value = material.color;
      uniforms.opacity.value = material.opacity;
    }
    function refreshUniformsDash(uniforms, material) {
      uniforms.dashSize.value = material.dashSize;
      uniforms.totalSize.value = material.dashSize + material.gapSize;
      uniforms.scale.value = material.scale;
    }
    function refreshUniformsPoints(uniforms, material) {
      uniforms.diffuse.value = material.color;
      uniforms.opacity.value = material.opacity;
      uniforms.size.value = material.size * _pixelRatio;
      uniforms.scale.value = _canvas.clientHeight * 0.5;
      uniforms.map.value = material.map;
      if (material.map !== null) {
        var offset = material.map.offset;
        var repeat = material.map.repeat;
        uniforms.offsetRepeat.value.set(offset.x, offset.y, repeat.x, repeat.y);
      }
    }
    function refreshUniformsFog(uniforms, fog) {
      uniforms.fogColor.value = fog.color;
      if (fog instanceof THREE.Fog) {
        uniforms.fogNear.value = fog.near;
        uniforms.fogFar.value = fog.far;
      } else if (fog instanceof THREE.FogExp2) {
        uniforms.fogDensity.value = fog.density;
      }
    }
    function refreshUniformsLambert(uniforms, material) {
      if (material.lightMap) {
        uniforms.lightMap.value = material.lightMap;
        uniforms.lightMapIntensity.value = material.lightMapIntensity;
      }
      if (material.emissiveMap) {
        uniforms.emissiveMap.value = material.emissiveMap;
      }
    }
    function refreshUniformsPhong(uniforms, material) {
      uniforms.specular.value = material.specular;
      uniforms.shininess.value = Math.max(material.shininess, 1e-4);
      if (material.lightMap) {
        uniforms.lightMap.value = material.lightMap;
        uniforms.lightMapIntensity.value = material.lightMapIntensity;
      }
      if (material.emissiveMap) {
        uniforms.emissiveMap.value = material.emissiveMap;
      }
      if (material.bumpMap) {
        uniforms.bumpMap.value = material.bumpMap;
        uniforms.bumpScale.value = material.bumpScale;
      }
      if (material.normalMap) {
        uniforms.normalMap.value = material.normalMap;
        uniforms.normalScale.value.copy(material.normalScale);
      }
      if (material.displacementMap) {
        uniforms.displacementMap.value = material.displacementMap;
        uniforms.displacementScale.value = material.displacementScale;
        uniforms.displacementBias.value = material.displacementBias;
      }
    }
    function refreshUniformsStandard(uniforms, material) {
      uniforms.roughness.value = material.roughness;
      uniforms.metalness.value = material.metalness;
      if (material.roughnessMap) {
        uniforms.roughnessMap.value = material.roughnessMap;
      }
      if (material.metalnessMap) {
        uniforms.metalnessMap.value = material.metalnessMap;
      }
      if (material.lightMap) {
        uniforms.lightMap.value = material.lightMap;
        uniforms.lightMapIntensity.value = material.lightMapIntensity;
      }
      if (material.emissiveMap) {
        uniforms.emissiveMap.value = material.emissiveMap;
      }
      if (material.bumpMap) {
        uniforms.bumpMap.value = material.bumpMap;
        uniforms.bumpScale.value = material.bumpScale;
      }
      if (material.normalMap) {
        uniforms.normalMap.value = material.normalMap;
        uniforms.normalScale.value.copy(material.normalScale);
      }
      if (material.displacementMap) {
        uniforms.displacementMap.value = material.displacementMap;
        uniforms.displacementScale.value = material.displacementScale;
        uniforms.displacementBias.value = material.displacementBias;
      }
      if (material.envMap) {
        uniforms.envMapIntensity.value = material.envMapIntensity;
      }
    }
    function refreshUniformsPhysical(uniforms, material) {
      uniforms.clearCoat.value = material.clearCoat;
      uniforms.clearCoatRoughness.value = material.clearCoatRoughness;
      refreshUniformsStandard(uniforms, material);
    }
    function markUniformsLightsNeedsUpdate(uniforms, value) {
      uniforms.ambientLightColor.needsUpdate = value;
      uniforms.directionalLights.needsUpdate = value;
      uniforms.pointLights.needsUpdate = value;
      uniforms.spotLights.needsUpdate = value;
      uniforms.hemisphereLights.needsUpdate = value;
    }
    function setupShadows(lights) {
      var lightShadowsLength = 0;
      for (var i = 0,
          l = lights.length; i < l; i++) {
        var light = lights[i];
        if (light.castShadow) {
          _lights.shadows[lightShadowsLength++] = light;
        }
      }
      _lights.shadows.length = lightShadowsLength;
    }
    function setupLights(lights, camera) {
      var l,
          ll,
          light,
          r = 0,
          g = 0,
          b = 0,
          color,
          intensity,
          distance,
          shadowMap,
          viewMatrix = camera.matrixWorldInverse,
          directionalLength = 0,
          pointLength = 0,
          spotLength = 0,
          hemiLength = 0;
      for (l = 0, ll = lights.length; l < ll; l++) {
        light = lights[l];
        color = light.color;
        intensity = light.intensity;
        distance = light.distance;
        shadowMap = (light.shadow && light.shadow.map) ? light.shadow.map.texture : null;
        if (light instanceof THREE.AmbientLight) {
          r += color.r * intensity;
          g += color.g * intensity;
          b += color.b * intensity;
        } else if (light instanceof THREE.DirectionalLight) {
          var uniforms = lightCache.get(light);
          uniforms.color.copy(light.color).multiplyScalar(light.intensity);
          uniforms.direction.setFromMatrixPosition(light.matrixWorld);
          _vector3.setFromMatrixPosition(light.target.matrixWorld);
          uniforms.direction.sub(_vector3);
          uniforms.direction.transformDirection(viewMatrix);
          uniforms.shadow = light.castShadow;
          if (light.castShadow) {
            uniforms.shadowBias = light.shadow.bias;
            uniforms.shadowRadius = light.shadow.radius;
            uniforms.shadowMapSize = light.shadow.mapSize;
          }
          _lights.directionalShadowMap[directionalLength] = shadowMap;
          _lights.directionalShadowMatrix[directionalLength] = light.shadow.matrix;
          _lights.directional[directionalLength++] = uniforms;
        } else if (light instanceof THREE.SpotLight) {
          var uniforms = lightCache.get(light);
          uniforms.position.setFromMatrixPosition(light.matrixWorld);
          uniforms.position.applyMatrix4(viewMatrix);
          uniforms.color.copy(color).multiplyScalar(intensity);
          uniforms.distance = distance;
          uniforms.direction.setFromMatrixPosition(light.matrixWorld);
          _vector3.setFromMatrixPosition(light.target.matrixWorld);
          uniforms.direction.sub(_vector3);
          uniforms.direction.transformDirection(viewMatrix);
          uniforms.coneCos = Math.cos(light.angle);
          uniforms.penumbraCos = Math.cos(light.angle * (1 - light.penumbra));
          uniforms.decay = (light.distance === 0) ? 0.0 : light.decay;
          uniforms.shadow = light.castShadow;
          if (light.castShadow) {
            uniforms.shadowBias = light.shadow.bias;
            uniforms.shadowRadius = light.shadow.radius;
            uniforms.shadowMapSize = light.shadow.mapSize;
          }
          _lights.spotShadowMap[spotLength] = shadowMap;
          _lights.spotShadowMatrix[spotLength] = light.shadow.matrix;
          _lights.spot[spotLength++] = uniforms;
        } else if (light instanceof THREE.PointLight) {
          var uniforms = lightCache.get(light);
          uniforms.position.setFromMatrixPosition(light.matrixWorld);
          uniforms.position.applyMatrix4(viewMatrix);
          uniforms.color.copy(light.color).multiplyScalar(light.intensity);
          uniforms.distance = light.distance;
          uniforms.decay = (light.distance === 0) ? 0.0 : light.decay;
          uniforms.shadow = light.castShadow;
          if (light.castShadow) {
            uniforms.shadowBias = light.shadow.bias;
            uniforms.shadowRadius = light.shadow.radius;
            uniforms.shadowMapSize = light.shadow.mapSize;
          }
          _lights.pointShadowMap[pointLength] = shadowMap;
          if (_lights.pointShadowMatrix[pointLength] === undefined) {
            _lights.pointShadowMatrix[pointLength] = new THREE.Matrix4();
          }
          _vector3.setFromMatrixPosition(light.matrixWorld).negate();
          _lights.pointShadowMatrix[pointLength].identity().setPosition(_vector3);
          _lights.point[pointLength++] = uniforms;
        } else if (light instanceof THREE.HemisphereLight) {
          var uniforms = lightCache.get(light);
          uniforms.direction.setFromMatrixPosition(light.matrixWorld);
          uniforms.direction.transformDirection(viewMatrix);
          uniforms.direction.normalize();
          uniforms.skyColor.copy(light.color).multiplyScalar(intensity);
          uniforms.groundColor.copy(light.groundColor).multiplyScalar(intensity);
          _lights.hemi[hemiLength++] = uniforms;
        }
      }
      _lights.ambient[0] = r;
      _lights.ambient[1] = g;
      _lights.ambient[2] = b;
      _lights.directional.length = directionalLength;
      _lights.spot.length = spotLength;
      _lights.point.length = pointLength;
      _lights.hemi.length = hemiLength;
      _lights.hash = directionalLength + ',' + pointLength + ',' + spotLength + ',' + hemiLength + ',' + _lights.shadows.length;
    }
    this.setFaceCulling = function(cullFace, frontFaceDirection) {
      state.setCullFace(cullFace);
      state.setFlipSided(frontFaceDirection === THREE.FrontFaceDirectionCW);
    };
    function allocTextureUnit() {
      var textureUnit = _usedTextureUnits;
      if (textureUnit >= capabilities.maxTextures) {
        console.warn('WebGLRenderer: trying to use ' + textureUnit + ' texture units while this GPU supports only ' + capabilities.maxTextures);
      }
      _usedTextureUnits += 1;
      return textureUnit;
    }
    this.allocTextureUnit = allocTextureUnit;
    this.setTexture2D = (function() {
      var warned = false;
      return function setTexture2D(texture, slot) {
        if (texture instanceof THREE.WebGLRenderTarget) {
          if (!warned) {
            console.warn("THREE.WebGLRenderer.setTexture2D: don't use render targets as textures. Use their .texture property instead.");
            warned = true;
          }
          texture = texture.texture;
        }
        textures.setTexture2D(texture, slot);
      };
    }());
    this.setTexture = (function() {
      var warned = false;
      return function setTexture(texture, slot) {
        if (!warned) {
          console.warn("THREE.WebGLRenderer: .setTexture is deprecated, use setTexture2D instead.");
          warned = true;
        }
        textures.setTexture2D(texture, slot);
      };
    }());
    this.setTextureCube = (function() {
      var warned = false;
      return function setTextureCube(texture, slot) {
        if (texture instanceof THREE.WebGLRenderTargetCube) {
          if (!warned) {
            console.warn("THREE.WebGLRenderer.setTextureCube: don't use cube render targets as textures. Use their .texture property instead.");
            warned = true;
          }
          texture = texture.texture;
        }
        if (texture instanceof THREE.CubeTexture || (Array.isArray(texture.image) && texture.image.length === 6)) {
          textures.setTextureCube(texture, slot);
        } else {
          textures.setTextureCubeDynamic(texture, slot);
        }
      };
    }());
    this.getCurrentRenderTarget = function() {
      return _currentRenderTarget;
    };
    this.setRenderTarget = function(renderTarget) {
      _currentRenderTarget = renderTarget;
      if (renderTarget && properties.get(renderTarget).__webglFramebuffer === undefined) {
        textures.setupRenderTarget(renderTarget);
      }
      var isCube = (renderTarget instanceof THREE.WebGLRenderTargetCube);
      var framebuffer;
      if (renderTarget) {
        var renderTargetProperties = properties.get(renderTarget);
        if (isCube) {
          framebuffer = renderTargetProperties.__webglFramebuffer[renderTarget.activeCubeFace];
        } else {
          framebuffer = renderTargetProperties.__webglFramebuffer;
        }
        _currentScissor.copy(renderTarget.scissor);
        _currentScissorTest = renderTarget.scissorTest;
        _currentViewport.copy(renderTarget.viewport);
      } else {
        framebuffer = null;
        _currentScissor.copy(_scissor).multiplyScalar(_pixelRatio);
        _currentScissorTest = _scissorTest;
        _currentViewport.copy(_viewport).multiplyScalar(_pixelRatio);
      }
      if (_currentFramebuffer !== framebuffer) {
        _gl.bindFramebuffer(_gl.FRAMEBUFFER, framebuffer);
        _currentFramebuffer = framebuffer;
      }
      state.scissor(_currentScissor);
      state.setScissorTest(_currentScissorTest);
      state.viewport(_currentViewport);
      if (isCube) {
        var textureProperties = properties.get(renderTarget.texture);
        _gl.framebufferTexture2D(_gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + renderTarget.activeCubeFace, textureProperties.__webglTexture, renderTarget.activeMipMapLevel);
      }
    };
    this.readRenderTargetPixels = function(renderTarget, x, y, width, height, buffer) {
      if (renderTarget instanceof THREE.WebGLRenderTarget === false) {
        console.error('THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.');
        return;
      }
      var framebuffer = properties.get(renderTarget).__webglFramebuffer;
      if (framebuffer) {
        var restore = false;
        if (framebuffer !== _currentFramebuffer) {
          _gl.bindFramebuffer(_gl.FRAMEBUFFER, framebuffer);
          restore = true;
        }
        try {
          var texture = renderTarget.texture;
          if (texture.format !== THREE.RGBAFormat && paramThreeToGL(texture.format) !== _gl.getParameter(_gl.IMPLEMENTATION_COLOR_READ_FORMAT)) {
            console.error('THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.');
            return;
          }
          if (texture.type !== THREE.UnsignedByteType && paramThreeToGL(texture.type) !== _gl.getParameter(_gl.IMPLEMENTATION_COLOR_READ_TYPE) && !(texture.type === THREE.FloatType && extensions.get('WEBGL_color_buffer_float')) && !(texture.type === THREE.HalfFloatType && extensions.get('EXT_color_buffer_half_float'))) {
            console.error('THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.');
            return;
          }
          if (_gl.checkFramebufferStatus(_gl.FRAMEBUFFER) === _gl.FRAMEBUFFER_COMPLETE) {
            if ((x >= 0 && x <= (renderTarget.width - width)) && (y >= 0 && y <= (renderTarget.height - height))) {
              _gl.readPixels(x, y, width, height, paramThreeToGL(texture.format), paramThreeToGL(texture.type), buffer);
            }
          } else {
            console.error('THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.');
          }
        } finally {
          if (restore) {
            _gl.bindFramebuffer(_gl.FRAMEBUFFER, _currentFramebuffer);
          }
        }
      }
    };
    function paramThreeToGL(p) {
      var extension;
      if (p === THREE.RepeatWrapping)
        return _gl.REPEAT;
      if (p === THREE.ClampToEdgeWrapping)
        return _gl.CLAMP_TO_EDGE;
      if (p === THREE.MirroredRepeatWrapping)
        return _gl.MIRRORED_REPEAT;
      if (p === THREE.NearestFilter)
        return _gl.NEAREST;
      if (p === THREE.NearestMipMapNearestFilter)
        return _gl.NEAREST_MIPMAP_NEAREST;
      if (p === THREE.NearestMipMapLinearFilter)
        return _gl.NEAREST_MIPMAP_LINEAR;
      if (p === THREE.LinearFilter)
        return _gl.LINEAR;
      if (p === THREE.LinearMipMapNearestFilter)
        return _gl.LINEAR_MIPMAP_NEAREST;
      if (p === THREE.LinearMipMapLinearFilter)
        return _gl.LINEAR_MIPMAP_LINEAR;
      if (p === THREE.UnsignedByteType)
        return _gl.UNSIGNED_BYTE;
      if (p === THREE.UnsignedShort4444Type)
        return _gl.UNSIGNED_SHORT_4_4_4_4;
      if (p === THREE.UnsignedShort5551Type)
        return _gl.UNSIGNED_SHORT_5_5_5_1;
      if (p === THREE.UnsignedShort565Type)
        return _gl.UNSIGNED_SHORT_5_6_5;
      if (p === THREE.ByteType)
        return _gl.BYTE;
      if (p === THREE.ShortType)
        return _gl.SHORT;
      if (p === THREE.UnsignedShortType)
        return _gl.UNSIGNED_SHORT;
      if (p === THREE.IntType)
        return _gl.INT;
      if (p === THREE.UnsignedIntType)
        return _gl.UNSIGNED_INT;
      if (p === THREE.FloatType)
        return _gl.FLOAT;
      extension = extensions.get('OES_texture_half_float');
      if (extension !== null) {
        if (p === THREE.HalfFloatType)
          return extension.HALF_FLOAT_OES;
      }
      if (p === THREE.AlphaFormat)
        return _gl.ALPHA;
      if (p === THREE.RGBFormat)
        return _gl.RGB;
      if (p === THREE.RGBAFormat)
        return _gl.RGBA;
      if (p === THREE.LuminanceFormat)
        return _gl.LUMINANCE;
      if (p === THREE.LuminanceAlphaFormat)
        return _gl.LUMINANCE_ALPHA;
      if (p === THREE.DepthFormat)
        return _gl.DEPTH_COMPONENT;
      if (p === THREE.AddEquation)
        return _gl.FUNC_ADD;
      if (p === THREE.SubtractEquation)
        return _gl.FUNC_SUBTRACT;
      if (p === THREE.ReverseSubtractEquation)
        return _gl.FUNC_REVERSE_SUBTRACT;
      if (p === THREE.ZeroFactor)
        return _gl.ZERO;
      if (p === THREE.OneFactor)
        return _gl.ONE;
      if (p === THREE.SrcColorFactor)
        return _gl.SRC_COLOR;
      if (p === THREE.OneMinusSrcColorFactor)
        return _gl.ONE_MINUS_SRC_COLOR;
      if (p === THREE.SrcAlphaFactor)
        return _gl.SRC_ALPHA;
      if (p === THREE.OneMinusSrcAlphaFactor)
        return _gl.ONE_MINUS_SRC_ALPHA;
      if (p === THREE.DstAlphaFactor)
        return _gl.DST_ALPHA;
      if (p === THREE.OneMinusDstAlphaFactor)
        return _gl.ONE_MINUS_DST_ALPHA;
      if (p === THREE.DstColorFactor)
        return _gl.DST_COLOR;
      if (p === THREE.OneMinusDstColorFactor)
        return _gl.ONE_MINUS_DST_COLOR;
      if (p === THREE.SrcAlphaSaturateFactor)
        return _gl.SRC_ALPHA_SATURATE;
      extension = extensions.get('WEBGL_compressed_texture_s3tc');
      if (extension !== null) {
        if (p === THREE.RGB_S3TC_DXT1_Format)
          return extension.COMPRESSED_RGB_S3TC_DXT1_EXT;
        if (p === THREE.RGBA_S3TC_DXT1_Format)
          return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT;
        if (p === THREE.RGBA_S3TC_DXT3_Format)
          return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT;
        if (p === THREE.RGBA_S3TC_DXT5_Format)
          return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT;
      }
      extension = extensions.get('WEBGL_compressed_texture_pvrtc');
      if (extension !== null) {
        if (p === THREE.RGB_PVRTC_4BPPV1_Format)
          return extension.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
        if (p === THREE.RGB_PVRTC_2BPPV1_Format)
          return extension.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
        if (p === THREE.RGBA_PVRTC_4BPPV1_Format)
          return extension.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
        if (p === THREE.RGBA_PVRTC_2BPPV1_Format)
          return extension.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
      }
      extension = extensions.get('WEBGL_compressed_texture_etc1');
      if (extension !== null) {
        if (p === THREE.RGB_ETC1_Format)
          return extension.COMPRESSED_RGB_ETC1_WEBGL;
      }
      extension = extensions.get('EXT_blend_minmax');
      if (extension !== null) {
        if (p === THREE.MinEquation)
          return extension.MIN_EXT;
        if (p === THREE.MaxEquation)
          return extension.MAX_EXT;
      }
      return 0;
    }
  };
  THREE.WebGLRenderTarget = function(width, height, options) {
    this.uuid = THREE.Math.generateUUID();
    this.width = width;
    this.height = height;
    this.scissor = new THREE.Vector4(0, 0, width, height);
    this.scissorTest = false;
    this.viewport = new THREE.Vector4(0, 0, width, height);
    options = options || {};
    if (options.minFilter === undefined)
      options.minFilter = THREE.LinearFilter;
    this.texture = new THREE.Texture(undefined, undefined, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding);
    this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true;
    this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : true;
    this.depthTexture = null;
  };
  Object.assign(THREE.WebGLRenderTarget.prototype, THREE.EventDispatcher.prototype, {
    setSize: function(width, height) {
      if (this.width !== width || this.height !== height) {
        this.width = width;
        this.height = height;
        this.dispose();
      }
      this.viewport.set(0, 0, width, height);
      this.scissor.set(0, 0, width, height);
    },
    clone: function() {
      return new this.constructor().copy(this);
    },
    copy: function(source) {
      this.width = source.width;
      this.height = source.height;
      this.viewport.copy(source.viewport);
      this.texture = source.texture.clone();
      this.depthBuffer = source.depthBuffer;
      this.stencilBuffer = source.stencilBuffer;
      this.depthTexture = source.depthTexture;
      return this;
    },
    dispose: function() {
      this.dispatchEvent({type: 'dispose'});
    }
  });
  THREE.WebGLRenderTargetCube = function(width, height, options) {
    THREE.WebGLRenderTarget.call(this, width, height, options);
    this.activeCubeFace = 0;
    this.activeMipMapLevel = 0;
  };
  THREE.WebGLRenderTargetCube.prototype = Object.create(THREE.WebGLRenderTarget.prototype);
  THREE.WebGLRenderTargetCube.prototype.constructor = THREE.WebGLRenderTargetCube;
  THREE.WebGLBufferRenderer = function(_gl, extensions, _infoRender) {
    var mode;
    function setMode(value) {
      mode = value;
    }
    function render(start, count) {
      _gl.drawArrays(mode, start, count);
      _infoRender.calls++;
      _infoRender.vertices += count;
      if (mode === _gl.TRIANGLES)
        _infoRender.faces += count / 3;
    }
    function renderInstances(geometry) {
      var extension = extensions.get('ANGLE_instanced_arrays');
      if (extension === null) {
        console.error('THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.');
        return;
      }
      var position = geometry.attributes.position;
      var count = 0;
      if (position instanceof THREE.InterleavedBufferAttribute) {
        count = position.data.count;
        extension.drawArraysInstancedANGLE(mode, 0, count, geometry.maxInstancedCount);
      } else {
        count = position.count;
        extension.drawArraysInstancedANGLE(mode, 0, count, geometry.maxInstancedCount);
      }
      _infoRender.calls++;
      _infoRender.vertices += count * geometry.maxInstancedCount;
      if (mode === _gl.TRIANGLES)
        _infoRender.faces += geometry.maxInstancedCount * count / 3;
    }
    this.setMode = setMode;
    this.render = render;
    this.renderInstances = renderInstances;
  };
  THREE.WebGLClipping = function() {
    var scope = this,
        globalState = null,
        numGlobalPlanes = 0,
        localClippingEnabled = false,
        renderingShadows = false,
        plane = new THREE.Plane(),
        viewNormalMatrix = new THREE.Matrix3(),
        uniform = {
          value: null,
          needsUpdate: false
        };
    this.uniform = uniform;
    this.numPlanes = 0;
    this.init = function(planes, enableLocalClipping, camera) {
      var enabled = planes.length !== 0 || enableLocalClipping || numGlobalPlanes !== 0 || localClippingEnabled;
      localClippingEnabled = enableLocalClipping;
      globalState = projectPlanes(planes, camera, 0);
      numGlobalPlanes = planes.length;
      return enabled;
    };
    this.beginShadows = function() {
      renderingShadows = true;
      projectPlanes(null);
    };
    this.endShadows = function() {
      renderingShadows = false;
      resetGlobalState();
    };
    this.setState = function(planes, clipShadows, camera, cache, fromCache) {
      if (!localClippingEnabled || planes === null || planes.length === 0 || renderingShadows && !clipShadows) {
        if (renderingShadows) {
          projectPlanes(null);
        } else {
          resetGlobalState();
        }
      } else {
        var nGlobal = renderingShadows ? 0 : numGlobalPlanes,
            lGlobal = nGlobal * 4,
            dstArray = cache.clippingState || null;
        uniform.value = dstArray;
        dstArray = projectPlanes(planes, camera, lGlobal, fromCache);
        for (var i = 0; i !== lGlobal; ++i) {
          dstArray[i] = globalState[i];
        }
        cache.clippingState = dstArray;
        this.numPlanes += nGlobal;
      }
    };
    function resetGlobalState() {
      if (uniform.value !== globalState) {
        uniform.value = globalState;
        uniform.needsUpdate = numGlobalPlanes > 0;
      }
      scope.numPlanes = numGlobalPlanes;
    }
    function projectPlanes(planes, camera, dstOffset, skipTransform) {
      var nPlanes = planes !== null ? planes.length : 0,
          dstArray = null;
      if (nPlanes !== 0) {
        dstArray = uniform.value;
        if (skipTransform !== true || dstArray === null) {
          var flatSize = dstOffset + nPlanes * 4,
              viewMatrix = camera.matrixWorldInverse;
          viewNormalMatrix.getNormalMatrix(viewMatrix);
          if (dstArray === null || dstArray.length < flatSize) {
            dstArray = new Float32Array(flatSize);
          }
          for (var i = 0,
              i4 = dstOffset; i !== nPlanes; ++i, i4 += 4) {
            plane.copy(planes[i]).applyMatrix4(viewMatrix, viewNormalMatrix);
            plane.normal.toArray(dstArray, i4);
            dstArray[i4 + 3] = plane.constant;
          }
        }
        uniform.value = dstArray;
        uniform.needsUpdate = true;
      }
      scope.numPlanes = nPlanes;
      return dstArray;
    }
  };
  THREE.WebGLIndexedBufferRenderer = function(_gl, extensions, _infoRender) {
    var mode;
    function setMode(value) {
      mode = value;
    }
    var type,
        size;
    function setIndex(index) {
      if (index.array instanceof Uint32Array && extensions.get('OES_element_index_uint')) {
        type = _gl.UNSIGNED_INT;
        size = 4;
      } else {
        type = _gl.UNSIGNED_SHORT;
        size = 2;
      }
    }
    function render(start, count) {
      _gl.drawElements(mode, count, type, start * size);
      _infoRender.calls++;
      _infoRender.vertices += count;
      if (mode === _gl.TRIANGLES)
        _infoRender.faces += count / 3;
    }
    function renderInstances(geometry, start, count) {
      var extension = extensions.get('ANGLE_instanced_arrays');
      if (extension === null) {
        console.error('THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.');
        return;
      }
      extension.drawElementsInstancedANGLE(mode, count, type, start * size, geometry.maxInstancedCount);
      _infoRender.calls++;
      _infoRender.vertices += count * geometry.maxInstancedCount;
      if (mode === _gl.TRIANGLES)
        _infoRender.faces += geometry.maxInstancedCount * count / 3;
    }
    this.setMode = setMode;
    this.setIndex = setIndex;
    this.render = render;
    this.renderInstances = renderInstances;
  };
  THREE.WebGLExtensions = function(gl) {
    var extensions = {};
    this.get = function(name) {
      if (extensions[name] !== undefined) {
        return extensions[name];
      }
      var extension;
      switch (name) {
        case 'WEBGL_depth_texture':
          extension = gl.getExtension('WEBGL_depth_texture') || gl.getExtension('MOZ_WEBGL_depth_texture') || gl.getExtension('WEBKIT_WEBGL_depth_texture');
          break;
        case 'EXT_texture_filter_anisotropic':
          extension = gl.getExtension('EXT_texture_filter_anisotropic') || gl.getExtension('MOZ_EXT_texture_filter_anisotropic') || gl.getExtension('WEBKIT_EXT_texture_filter_anisotropic');
          break;
        case 'WEBGL_compressed_texture_s3tc':
          extension = gl.getExtension('WEBGL_compressed_texture_s3tc') || gl.getExtension('MOZ_WEBGL_compressed_texture_s3tc') || gl.getExtension('WEBKIT_WEBGL_compressed_texture_s3tc');
          break;
        case 'WEBGL_compressed_texture_pvrtc':
          extension = gl.getExtension('WEBGL_compressed_texture_pvrtc') || gl.getExtension('WEBKIT_WEBGL_compressed_texture_pvrtc');
          break;
        case 'WEBGL_compressed_texture_etc1':
          extension = gl.getExtension('WEBGL_compressed_texture_etc1');
          break;
        default:
          extension = gl.getExtension(name);
      }
      if (extension === null) {
        console.warn('THREE.WebGLRenderer: ' + name + ' extension not supported.');
      }
      extensions[name] = extension;
      return extension;
    };
  };
  THREE.WebGLCapabilities = function(gl, extensions, parameters) {
    var maxAnisotropy;
    function getMaxAnisotropy() {
      if (maxAnisotropy !== undefined)
        return maxAnisotropy;
      var extension = extensions.get('EXT_texture_filter_anisotropic');
      if (extension !== null) {
        maxAnisotropy = gl.getParameter(extension.MAX_TEXTURE_MAX_ANISOTROPY_EXT);
      } else {
        maxAnisotropy = 0;
      }
      return maxAnisotropy;
    }
    function getMaxPrecision(precision) {
      if (precision === 'highp') {
        if (gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.HIGH_FLOAT).precision > 0 && gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_FLOAT).precision > 0) {
          return 'highp';
        }
        precision = 'mediump';
      }
      if (precision === 'mediump') {
        if (gl.getShaderPrecisionFormat(gl.VERTEX_SHADER, gl.MEDIUM_FLOAT).precision > 0 && gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT).precision > 0) {
          return 'mediump';
        }
      }
      return 'lowp';
    }
    this.getMaxAnisotropy = getMaxAnisotropy;
    this.getMaxPrecision = getMaxPrecision;
    this.precision = parameters.precision !== undefined ? parameters.precision : 'highp';
    this.logarithmicDepthBuffer = parameters.logarithmicDepthBuffer !== undefined ? parameters.logarithmicDepthBuffer : false;
    this.maxTextures = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS);
    this.maxVertexTextures = gl.getParameter(gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS);
    this.maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE);
    this.maxCubemapSize = gl.getParameter(gl.MAX_CUBE_MAP_TEXTURE_SIZE);
    this.maxAttributes = gl.getParameter(gl.MAX_VERTEX_ATTRIBS);
    this.maxVertexUniforms = gl.getParameter(gl.MAX_VERTEX_UNIFORM_VECTORS);
    this.maxVaryings = gl.getParameter(gl.MAX_VARYING_VECTORS);
    this.maxFragmentUniforms = gl.getParameter(gl.MAX_FRAGMENT_UNIFORM_VECTORS);
    this.vertexTextures = this.maxVertexTextures > 0;
    this.floatFragmentTextures = !!extensions.get('OES_texture_float');
    this.floatVertexTextures = this.vertexTextures && this.floatFragmentTextures;
    var _maxPrecision = getMaxPrecision(this.precision);
    if (_maxPrecision !== this.precision) {
      console.warn('THREE.WebGLRenderer:', this.precision, 'not supported, using', _maxPrecision, 'instead.');
      this.precision = _maxPrecision;
    }
    if (this.logarithmicDepthBuffer) {
      this.logarithmicDepthBuffer = !!extensions.get('EXT_frag_depth');
    }
  };
  THREE.WebGLGeometries = function(gl, properties, info) {
    var geometries = {};
    function get(object) {
      var geometry = object.geometry;
      if (geometries[geometry.id] !== undefined) {
        return geometries[geometry.id];
      }
      geometry.addEventListener('dispose', onGeometryDispose);
      var buffergeometry;
      if (geometry instanceof THREE.BufferGeometry) {
        buffergeometry = geometry;
      } else if (geometry instanceof THREE.Geometry) {
        if (geometry._bufferGeometry === undefined) {
          geometry._bufferGeometry = new THREE.BufferGeometry().setFromObject(object);
        }
        buffergeometry = geometry._bufferGeometry;
      }
      geometries[geometry.id] = buffergeometry;
      info.memory.geometries++;
      return buffergeometry;
    }
    function onGeometryDispose(event) {
      var geometry = event.target;
      var buffergeometry = geometries[geometry.id];
      if (buffergeometry.index !== null) {
        deleteAttribute(buffergeometry.index);
      }
      deleteAttributes(buffergeometry.attributes);
      geometry.removeEventListener('dispose', onGeometryDispose);
      delete geometries[geometry.id];
      var property = properties.get(geometry);
      if (property.wireframe) {
        deleteAttribute(property.wireframe);
      }
      properties.delete(geometry);
      var bufferproperty = properties.get(buffergeometry);
      if (bufferproperty.wireframe) {
        deleteAttribute(bufferproperty.wireframe);
      }
      properties.delete(buffergeometry);
      info.memory.geometries--;
    }
    function getAttributeBuffer(attribute) {
      if (attribute instanceof THREE.InterleavedBufferAttribute) {
        return properties.get(attribute.data).__webglBuffer;
      }
      return properties.get(attribute).__webglBuffer;
    }
    function deleteAttribute(attribute) {
      var buffer = getAttributeBuffer(attribute);
      if (buffer !== undefined) {
        gl.deleteBuffer(buffer);
        removeAttributeBuffer(attribute);
      }
    }
    function deleteAttributes(attributes) {
      for (var name in attributes) {
        deleteAttribute(attributes[name]);
      }
    }
    function removeAttributeBuffer(attribute) {
      if (attribute instanceof THREE.InterleavedBufferAttribute) {
        properties.delete(attribute.data);
      } else {
        properties.delete(attribute);
      }
    }
    this.get = get;
  };
  THREE.WebGLLights = function() {
    var lights = {};
    this.get = function(light) {
      if (lights[light.id] !== undefined) {
        return lights[light.id];
      }
      var uniforms;
      switch (light.type) {
        case 'DirectionalLight':
          uniforms = {
            direction: new THREE.Vector3(),
            color: new THREE.Color(),
            shadow: false,
            shadowBias: 0,
            shadowRadius: 1,
            shadowMapSize: new THREE.Vector2()
          };
          break;
        case 'SpotLight':
          uniforms = {
            position: new THREE.Vector3(),
            direction: new THREE.Vector3(),
            color: new THREE.Color(),
            distance: 0,
            coneCos: 0,
            penumbraCos: 0,
            decay: 0,
            shadow: false,
            shadowBias: 0,
            shadowRadius: 1,
            shadowMapSize: new THREE.Vector2()
          };
          break;
        case 'PointLight':
          uniforms = {
            position: new THREE.Vector3(),
            color: new THREE.Color(),
            distance: 0,
            decay: 0,
            shadow: false,
            shadowBias: 0,
            shadowRadius: 1,
            shadowMapSize: new THREE.Vector2()
          };
          break;
        case 'HemisphereLight':
          uniforms = {
            direction: new THREE.Vector3(),
            skyColor: new THREE.Color(),
            groundColor: new THREE.Color()
          };
          break;
      }
      lights[light.id] = uniforms;
      return uniforms;
    };
  };
  THREE.WebGLObjects = function(gl, properties, info) {
    var geometries = new THREE.WebGLGeometries(gl, properties, info);
    function update(object) {
      var geometry = geometries.get(object);
      if (object.geometry instanceof THREE.Geometry) {
        geometry.updateFromObject(object);
      }
      var index = geometry.index;
      var attributes = geometry.attributes;
      if (index !== null) {
        updateAttribute(index, gl.ELEMENT_ARRAY_BUFFER);
      }
      for (var name in attributes) {
        updateAttribute(attributes[name], gl.ARRAY_BUFFER);
      }
      var morphAttributes = geometry.morphAttributes;
      for (var name in morphAttributes) {
        var array = morphAttributes[name];
        for (var i = 0,
            l = array.length; i < l; i++) {
          updateAttribute(array[i], gl.ARRAY_BUFFER);
        }
      }
      return geometry;
    }
    function updateAttribute(attribute, bufferType) {
      var data = (attribute instanceof THREE.InterleavedBufferAttribute) ? attribute.data : attribute;
      var attributeProperties = properties.get(data);
      if (attributeProperties.__webglBuffer === undefined) {
        createBuffer(attributeProperties, data, bufferType);
      } else if (attributeProperties.version !== data.version) {
        updateBuffer(attributeProperties, data, bufferType);
      }
    }
    function createBuffer(attributeProperties, data, bufferType) {
      attributeProperties.__webglBuffer = gl.createBuffer();
      gl.bindBuffer(bufferType, attributeProperties.__webglBuffer);
      var usage = data.dynamic ? gl.DYNAMIC_DRAW : gl.STATIC_DRAW;
      gl.bufferData(bufferType, data.array, usage);
      attributeProperties.version = data.version;
    }
    function updateBuffer(attributeProperties, data, bufferType) {
      gl.bindBuffer(bufferType, attributeProperties.__webglBuffer);
      if (data.dynamic === false || data.updateRange.count === -1) {
        gl.bufferSubData(bufferType, 0, data.array);
      } else if (data.updateRange.count === 0) {
        console.error('THREE.WebGLObjects.updateBuffer: dynamic THREE.BufferAttribute marked as needsUpdate but updateRange.count is 0, ensure you are using set methods or updating manually.');
      } else {
        gl.bufferSubData(bufferType, data.updateRange.offset * data.array.BYTES_PER_ELEMENT, data.array.subarray(data.updateRange.offset, data.updateRange.offset + data.updateRange.count));
        data.updateRange.count = 0;
      }
      attributeProperties.version = data.version;
    }
    function getAttributeBuffer(attribute) {
      if (attribute instanceof THREE.InterleavedBufferAttribute) {
        return properties.get(attribute.data).__webglBuffer;
      }
      return properties.get(attribute).__webglBuffer;
    }
    function getWireframeAttribute(geometry) {
      var property = properties.get(geometry);
      if (property.wireframe !== undefined) {
        return property.wireframe;
      }
      var indices = [];
      var index = geometry.index;
      var attributes = geometry.attributes;
      var position = attributes.position;
      if (index !== null) {
        var edges = {};
        var array = index.array;
        for (var i = 0,
            l = array.length; i < l; i += 3) {
          var a = array[i + 0];
          var b = array[i + 1];
          var c = array[i + 2];
          if (checkEdge(edges, a, b))
            indices.push(a, b);
          if (checkEdge(edges, b, c))
            indices.push(b, c);
          if (checkEdge(edges, c, a))
            indices.push(c, a);
        }
      } else {
        var array = attributes.position.array;
        for (var i = 0,
            l = (array.length / 3) - 1; i < l; i += 3) {
          var a = i + 0;
          var b = i + 1;
          var c = i + 2;
          indices.push(a, b, b, c, c, a);
        }
      }
      var TypeArray = position.count > 65535 ? Uint32Array : Uint16Array;
      var attribute = new THREE.BufferAttribute(new TypeArray(indices), 1);
      updateAttribute(attribute, gl.ELEMENT_ARRAY_BUFFER);
      property.wireframe = attribute;
      return attribute;
    }
    function checkEdge(edges, a, b) {
      if (a > b) {
        var tmp = a;
        a = b;
        b = tmp;
      }
      var list = edges[a];
      if (list === undefined) {
        edges[a] = [b];
        return true;
      } else if (list.indexOf(b) === -1) {
        list.push(b);
        return true;
      }
      return false;
    }
    this.getAttributeBuffer = getAttributeBuffer;
    this.getWireframeAttribute = getWireframeAttribute;
    this.update = update;
  };
  THREE.WebGLProgram = (function() {
    var programIdCount = 0;
    function getEncodingComponents(encoding) {
      switch (encoding) {
        case THREE.LinearEncoding:
          return ['Linear', '( value )'];
        case THREE.sRGBEncoding:
          return ['sRGB', '( value )'];
        case THREE.RGBEEncoding:
          return ['RGBE', '( value )'];
        case THREE.RGBM7Encoding:
          return ['RGBM', '( value, 7.0 )'];
        case THREE.RGBM16Encoding:
          return ['RGBM', '( value, 16.0 )'];
        case THREE.RGBDEncoding:
          return ['RGBD', '( value, 256.0 )'];
        case THREE.GammaEncoding:
          return ['Gamma', '( value, float( GAMMA_FACTOR ) )'];
        default:
          throw new Error('unsupported encoding: ' + encoding);
      }
    }
    function getTexelDecodingFunction(functionName, encoding) {
      var components = getEncodingComponents(encoding);
      return "vec4 " + functionName + "( vec4 value ) { return " + components[0] + "ToLinear" + components[1] + "; }";
    }
    function getTexelEncodingFunction(functionName, encoding) {
      var components = getEncodingComponents(encoding);
      return "vec4 " + functionName + "( vec4 value ) { return LinearTo" + components[0] + components[1] + "; }";
    }
    function getToneMappingFunction(functionName, toneMapping) {
      var toneMappingName;
      switch (toneMapping) {
        case THREE.LinearToneMapping:
          toneMappingName = "Linear";
          break;
        case THREE.ReinhardToneMapping:
          toneMappingName = "Reinhard";
          break;
        case THREE.Uncharted2ToneMapping:
          toneMappingName = "Uncharted2";
          break;
        case THREE.CineonToneMapping:
          toneMappingName = "OptimizedCineon";
          break;
        default:
          throw new Error('unsupported toneMapping: ' + toneMapping);
      }
      return "vec3 " + functionName + "( vec3 color ) { return " + toneMappingName + "ToneMapping( color ); }";
    }
    function generateExtensions(extensions, parameters, rendererExtensions) {
      extensions = extensions || {};
      var chunks = [(extensions.derivatives || parameters.envMapCubeUV || parameters.bumpMap || parameters.normalMap || parameters.flatShading) ? '#extension GL_OES_standard_derivatives : enable' : '', (extensions.fragDepth || parameters.logarithmicDepthBuffer) && rendererExtensions.get('EXT_frag_depth') ? '#extension GL_EXT_frag_depth : enable' : '', (extensions.drawBuffers) && rendererExtensions.get('WEBGL_draw_buffers') ? '#extension GL_EXT_draw_buffers : require' : '', (extensions.shaderTextureLOD || parameters.envMap) && rendererExtensions.get('EXT_shader_texture_lod') ? '#extension GL_EXT_shader_texture_lod : enable' : ''];
      return chunks.filter(filterEmptyLine).join('\n');
    }
    function generateDefines(defines) {
      var chunks = [];
      for (var name in defines) {
        var value = defines[name];
        if (value === false)
          continue;
        chunks.push('#define ' + name + ' ' + value);
      }
      return chunks.join('\n');
    }
    function fetchAttributeLocations(gl, program, identifiers) {
      var attributes = {};
      var n = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES);
      for (var i = 0; i < n; i++) {
        var info = gl.getActiveAttrib(program, i);
        var name = info.name;
        attributes[name] = gl.getAttribLocation(program, name);
      }
      return attributes;
    }
    function filterEmptyLine(string) {
      return string !== '';
    }
    function replaceLightNums(string, parameters) {
      return string.replace(/NUM_DIR_LIGHTS/g, parameters.numDirLights).replace(/NUM_SPOT_LIGHTS/g, parameters.numSpotLights).replace(/NUM_POINT_LIGHTS/g, parameters.numPointLights).replace(/NUM_HEMI_LIGHTS/g, parameters.numHemiLights);
    }
    function parseIncludes(string) {
      var pattern = /#include +<([\w\d.]+)>/g;
      function replace(match, include) {
        var replace = THREE.ShaderChunk[include];
        if (replace === undefined) {
          throw new Error('Can not resolve #include <' + include + '>');
        }
        return parseIncludes(replace);
      }
      return string.replace(pattern, replace);
    }
    function unrollLoops(string) {
      var pattern = /for \( int i \= (\d+)\; i < (\d+)\; i \+\+ \) \{([\s\S]+?)(?=\})\}/g;
      function replace(match, start, end, snippet) {
        var unroll = '';
        for (var i = parseInt(start); i < parseInt(end); i++) {
          unroll += snippet.replace(/\[ i \]/g, '[ ' + i + ' ]');
        }
        return unroll;
      }
      return string.replace(pattern, replace);
    }
    return function WebGLProgram(renderer, code, material, parameters) {
      var gl = renderer.context;
      var extensions = material.extensions;
      var defines = material.defines;
      var vertexShader = material.__webglShader.vertexShader;
      var fragmentShader = material.__webglShader.fragmentShader;
      var shadowMapTypeDefine = 'SHADOWMAP_TYPE_BASIC';
      if (parameters.shadowMapType === THREE.PCFShadowMap) {
        shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF';
      } else if (parameters.shadowMapType === THREE.PCFSoftShadowMap) {
        shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT';
      }
      var envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
      var envMapModeDefine = 'ENVMAP_MODE_REFLECTION';
      var envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY';
      if (parameters.envMap) {
        switch (material.envMap.mapping) {
          case THREE.CubeReflectionMapping:
          case THREE.CubeRefractionMapping:
            envMapTypeDefine = 'ENVMAP_TYPE_CUBE';
            break;
          case THREE.CubeUVReflectionMapping:
          case THREE.CubeUVRefractionMapping:
            envMapTypeDefine = 'ENVMAP_TYPE_CUBE_UV';
            break;
          case THREE.EquirectangularReflectionMapping:
          case THREE.EquirectangularRefractionMapping:
            envMapTypeDefine = 'ENVMAP_TYPE_EQUIREC';
            break;
          case THREE.SphericalReflectionMapping:
            envMapTypeDefine = 'ENVMAP_TYPE_SPHERE';
            break;
        }
        switch (material.envMap.mapping) {
          case THREE.CubeRefractionMapping:
          case THREE.EquirectangularRefractionMapping:
            envMapModeDefine = 'ENVMAP_MODE_REFRACTION';
            break;
        }
        switch (material.combine) {
          case THREE.MultiplyOperation:
            envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY';
            break;
          case THREE.MixOperation:
            envMapBlendingDefine = 'ENVMAP_BLENDING_MIX';
            break;
          case THREE.AddOperation:
            envMapBlendingDefine = 'ENVMAP_BLENDING_ADD';
            break;
        }
      }
      var gammaFactorDefine = (renderer.gammaFactor > 0) ? renderer.gammaFactor : 1.0;
      var customExtensions = generateExtensions(extensions, parameters, renderer.extensions);
      var customDefines = generateDefines(defines);
      var program = gl.createProgram();
      var prefixVertex,
          prefixFragment;
      if (material instanceof THREE.RawShaderMaterial) {
        prefixVertex = [customDefines].filter(filterEmptyLine).join('\n');
        prefixFragment = [customDefines].filter(filterEmptyLine).join('\n');
      } else {
        prefixVertex = ['precision ' + parameters.precision + ' float;', 'precision ' + parameters.precision + ' int;', '#define SHADER_NAME ' + material.__webglShader.name, customDefines, parameters.supportsVertexTextures ? '#define VERTEX_TEXTURES' : '', '#define GAMMA_FACTOR ' + gammaFactorDefine, '#define MAX_BONES ' + parameters.maxBones, parameters.map ? '#define USE_MAP' : '', parameters.envMap ? '#define USE_ENVMAP' : '', parameters.envMap ? '#define ' + envMapModeDefine : '', parameters.lightMap ? '#define USE_LIGHTMAP' : '', parameters.aoMap ? '#define USE_AOMAP' : '', parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '', parameters.bumpMap ? '#define USE_BUMPMAP' : '', parameters.normalMap ? '#define USE_NORMALMAP' : '', parameters.displacementMap && parameters.supportsVertexTextures ? '#define USE_DISPLACEMENTMAP' : '', parameters.specularMap ? '#define USE_SPECULARMAP' : '', parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '', parameters.metalnessMap ? '#define USE_METALNESSMAP' : '', parameters.alphaMap ? '#define USE_ALPHAMAP' : '', parameters.vertexColors ? '#define USE_COLOR' : '', parameters.flatShading ? '#define FLAT_SHADED' : '', parameters.skinning ? '#define USE_SKINNING' : '', parameters.useVertexTexture ? '#define BONE_TEXTURE' : '', parameters.morphTargets ? '#define USE_MORPHTARGETS' : '', parameters.morphNormals && parameters.flatShading === false ? '#define USE_MORPHNORMALS' : '', parameters.doubleSided ? '#define DOUBLE_SIDED' : '', parameters.flipSided ? '#define FLIP_SIDED' : '', '#define NUM_CLIPPING_PLANES ' + parameters.numClippingPlanes, parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '', parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '', parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '', parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', parameters.logarithmicDepthBuffer && renderer.extensions.get('EXT_frag_depth') ? '#define USE_LOGDEPTHBUF_EXT' : '', 'uniform mat4 modelMatrix;', 'uniform mat4 modelViewMatrix;', 'uniform mat4 projectionMatrix;', 'uniform mat4 viewMatrix;', 'uniform mat3 normalMatrix;', 'uniform vec3 cameraPosition;', 'attribute vec3 position;', 'attribute vec3 normal;', 'attribute vec2 uv;', '#ifdef USE_COLOR', '	attribute vec3 color;', '#endif', '#ifdef USE_MORPHTARGETS', '	attribute vec3 morphTarget0;', '	attribute vec3 morphTarget1;', '	attribute vec3 morphTarget2;', '	attribute vec3 morphTarget3;', '	#ifdef USE_MORPHNORMALS', '		attribute vec3 morphNormal0;', '		attribute vec3 morphNormal1;', '		attribute vec3 morphNormal2;', '		attribute vec3 morphNormal3;', '	#else', '		attribute vec3 morphTarget4;', '		attribute vec3 morphTarget5;', '		attribute vec3 morphTarget6;', '		attribute vec3 morphTarget7;', '	#endif', '#endif', '#ifdef USE_SKINNING', '	attribute vec4 skinIndex;', '	attribute vec4 skinWeight;', '#endif', '\n'].filter(filterEmptyLine).join('\n');
        prefixFragment = [customExtensions, 'precision ' + parameters.precision + ' float;', 'precision ' + parameters.precision + ' int;', '#define SHADER_NAME ' + material.__webglShader.name, customDefines, parameters.alphaTest ? '#define ALPHATEST ' + parameters.alphaTest : '', '#define GAMMA_FACTOR ' + gammaFactorDefine, (parameters.useFog && parameters.fog) ? '#define USE_FOG' : '', (parameters.useFog && parameters.fogExp) ? '#define FOG_EXP2' : '', parameters.map ? '#define USE_MAP' : '', parameters.envMap ? '#define USE_ENVMAP' : '', parameters.envMap ? '#define ' + envMapTypeDefine : '', parameters.envMap ? '#define ' + envMapModeDefine : '', parameters.envMap ? '#define ' + envMapBlendingDefine : '', parameters.lightMap ? '#define USE_LIGHTMAP' : '', parameters.aoMap ? '#define USE_AOMAP' : '', parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '', parameters.bumpMap ? '#define USE_BUMPMAP' : '', parameters.normalMap ? '#define USE_NORMALMAP' : '', parameters.specularMap ? '#define USE_SPECULARMAP' : '', parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '', parameters.metalnessMap ? '#define USE_METALNESSMAP' : '', parameters.alphaMap ? '#define USE_ALPHAMAP' : '', parameters.vertexColors ? '#define USE_COLOR' : '', parameters.flatShading ? '#define FLAT_SHADED' : '', parameters.doubleSided ? '#define DOUBLE_SIDED' : '', parameters.flipSided ? '#define FLIP_SIDED' : '', '#define NUM_CLIPPING_PLANES ' + parameters.numClippingPlanes, parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '', parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '', parameters.premultipliedAlpha ? "#define PREMULTIPLIED_ALPHA" : '', parameters.physicallyCorrectLights ? "#define PHYSICALLY_CORRECT_LIGHTS" : '', parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', parameters.logarithmicDepthBuffer && renderer.extensions.get('EXT_frag_depth') ? '#define USE_LOGDEPTHBUF_EXT' : '', parameters.envMap && renderer.extensions.get('EXT_shader_texture_lod') ? '#define TEXTURE_LOD_EXT' : '', 'uniform mat4 viewMatrix;', 'uniform vec3 cameraPosition;', (parameters.toneMapping !== THREE.NoToneMapping) ? "#define TONE_MAPPING" : '', (parameters.toneMapping !== THREE.NoToneMapping) ? THREE.ShaderChunk['tonemapping_pars_fragment'] : '', (parameters.toneMapping !== THREE.NoToneMapping) ? getToneMappingFunction("toneMapping", parameters.toneMapping) : '', (parameters.outputEncoding || parameters.mapEncoding || parameters.envMapEncoding || parameters.emissiveMapEncoding) ? THREE.ShaderChunk['encodings_pars_fragment'] : '', parameters.mapEncoding ? getTexelDecodingFunction('mapTexelToLinear', parameters.mapEncoding) : '', parameters.envMapEncoding ? getTexelDecodingFunction('envMapTexelToLinear', parameters.envMapEncoding) : '', parameters.emissiveMapEncoding ? getTexelDecodingFunction('emissiveMapTexelToLinear', parameters.emissiveMapEncoding) : '', parameters.outputEncoding ? getTexelEncodingFunction("linearToOutputTexel", parameters.outputEncoding) : '', parameters.depthPacking ? "#define DEPTH_PACKING " + material.depthPacking : '', '\n'].filter(filterEmptyLine).join('\n');
      }
      vertexShader = parseIncludes(vertexShader, parameters);
      vertexShader = replaceLightNums(vertexShader, parameters);
      fragmentShader = parseIncludes(fragmentShader, parameters);
      fragmentShader = replaceLightNums(fragmentShader, parameters);
      if (material instanceof THREE.ShaderMaterial === false) {
        vertexShader = unrollLoops(vertexShader);
        fragmentShader = unrollLoops(fragmentShader);
      }
      var vertexGlsl = prefixVertex + vertexShader;
      var fragmentGlsl = prefixFragment + fragmentShader;
      var glVertexShader = THREE.WebGLShader(gl, gl.VERTEX_SHADER, vertexGlsl);
      var glFragmentShader = THREE.WebGLShader(gl, gl.FRAGMENT_SHADER, fragmentGlsl);
      gl.attachShader(program, glVertexShader);
      gl.attachShader(program, glFragmentShader);
      if (material.index0AttributeName !== undefined) {
        gl.bindAttribLocation(program, 0, material.index0AttributeName);
      } else if (parameters.morphTargets === true) {
        gl.bindAttribLocation(program, 0, 'position');
      }
      gl.linkProgram(program);
      var programLog = gl.getProgramInfoLog(program);
      var vertexLog = gl.getShaderInfoLog(glVertexShader);
      var fragmentLog = gl.getShaderInfoLog(glFragmentShader);
      var runnable = true;
      var haveDiagnostics = true;
      if (gl.getProgramParameter(program, gl.LINK_STATUS) === false) {
        runnable = false;
        console.error('THREE.WebGLProgram: shader error: ', gl.getError(), 'gl.VALIDATE_STATUS', gl.getProgramParameter(program, gl.VALIDATE_STATUS), 'gl.getProgramInfoLog', programLog, vertexLog, fragmentLog);
      } else if (programLog !== '') {
        console.warn('THREE.WebGLProgram: gl.getProgramInfoLog()', programLog);
      } else if (vertexLog === '' || fragmentLog === '') {
        haveDiagnostics = false;
      }
      if (haveDiagnostics) {
        this.diagnostics = {
          runnable: runnable,
          material: material,
          programLog: programLog,
          vertexShader: {
            log: vertexLog,
            prefix: prefixVertex
          },
          fragmentShader: {
            log: fragmentLog,
            prefix: prefixFragment
          }
        };
      }
      gl.deleteShader(glVertexShader);
      gl.deleteShader(glFragmentShader);
      var cachedUniforms;
      this.getUniforms = function() {
        if (cachedUniforms === undefined) {
          cachedUniforms = new THREE.WebGLUniforms(gl, program, renderer);
        }
        return cachedUniforms;
      };
      var cachedAttributes;
      this.getAttributes = function() {
        if (cachedAttributes === undefined) {
          cachedAttributes = fetchAttributeLocations(gl, program);
        }
        return cachedAttributes;
      };
      this.destroy = function() {
        gl.deleteProgram(program);
        this.program = undefined;
      };
      Object.defineProperties(this, {
        uniforms: {get: function() {
            console.warn('THREE.WebGLProgram: .uniforms is now .getUniforms().');
            return this.getUniforms();
          }},
        attributes: {get: function() {
            console.warn('THREE.WebGLProgram: .attributes is now .getAttributes().');
            return this.getAttributes();
          }}
      });
      this.id = programIdCount++;
      this.code = code;
      this.usedTimes = 1;
      this.program = program;
      this.vertexShader = glVertexShader;
      this.fragmentShader = glFragmentShader;
      return this;
    };
  })();
  THREE.WebGLPrograms = function(renderer, capabilities) {
    var programs = [];
    var shaderIDs = {
      MeshDepthMaterial: 'depth',
      MeshNormalMaterial: 'normal',
      MeshBasicMaterial: 'basic',
      MeshLambertMaterial: 'lambert',
      MeshPhongMaterial: 'phong',
      MeshStandardMaterial: 'physical',
      MeshPhysicalMaterial: 'physical',
      LineBasicMaterial: 'basic',
      LineDashedMaterial: 'dashed',
      PointsMaterial: 'points'
    };
    var parameterNames = ["precision", "supportsVertexTextures", "map", "mapEncoding", "envMap", "envMapMode", "envMapEncoding", "lightMap", "aoMap", "emissiveMap", "emissiveMapEncoding", "bumpMap", "normalMap", "displacementMap", "specularMap", "roughnessMap", "metalnessMap", "alphaMap", "combine", "vertexColors", "fog", "useFog", "fogExp", "flatShading", "sizeAttenuation", "logarithmicDepthBuffer", "skinning", "maxBones", "useVertexTexture", "morphTargets", "morphNormals", "maxMorphTargets", "maxMorphNormals", "premultipliedAlpha", "numDirLights", "numPointLights", "numSpotLights", "numHemiLights", "shadowMapEnabled", "shadowMapType", "toneMapping", 'physicallyCorrectLights', "alphaTest", "doubleSided", "flipSided", "numClippingPlanes", "depthPacking"];
    function allocateBones(object) {
      if (capabilities.floatVertexTextures && object && object.skeleton && object.skeleton.useVertexTexture) {
        return 1024;
      } else {
        var nVertexUniforms = capabilities.maxVertexUniforms;
        var nVertexMatrices = Math.floor((nVertexUniforms - 20) / 4);
        var maxBones = nVertexMatrices;
        if (object !== undefined && object instanceof THREE.SkinnedMesh) {
          maxBones = Math.min(object.skeleton.bones.length, maxBones);
          if (maxBones < object.skeleton.bones.length) {
            console.warn('WebGLRenderer: too many bones - ' + object.skeleton.bones.length + ', this GPU supports just ' + maxBones + ' (try OpenGL instead of ANGLE)');
          }
        }
        return maxBones;
      }
    }
    function getTextureEncodingFromMap(map, gammaOverrideLinear) {
      var encoding;
      if (!map) {
        encoding = THREE.LinearEncoding;
      } else if (map instanceof THREE.Texture) {
        encoding = map.encoding;
      } else if (map instanceof THREE.WebGLRenderTarget) {
        console.warn("THREE.WebGLPrograms.getTextureEncodingFromMap: don't use render targets as textures. Use their .texture property instead.");
        encoding = map.texture.encoding;
      }
      if (encoding === THREE.LinearEncoding && gammaOverrideLinear) {
        encoding = THREE.GammaEncoding;
      }
      return encoding;
    }
    this.getParameters = function(material, lights, fog, nClipPlanes, object) {
      var shaderID = shaderIDs[material.type];
      var maxBones = allocateBones(object);
      var precision = renderer.getPrecision();
      if (material.precision !== null) {
        precision = capabilities.getMaxPrecision(material.precision);
        if (precision !== material.precision) {
          console.warn('THREE.WebGLProgram.getParameters:', material.precision, 'not supported, using', precision, 'instead.');
        }
      }
      var currentRenderTarget = renderer.getCurrentRenderTarget();
      var parameters = {
        shaderID: shaderID,
        precision: precision,
        supportsVertexTextures: capabilities.vertexTextures,
        outputEncoding: getTextureEncodingFromMap((!currentRenderTarget) ? null : currentRenderTarget.texture, renderer.gammaOutput),
        map: !!material.map,
        mapEncoding: getTextureEncodingFromMap(material.map, renderer.gammaInput),
        envMap: !!material.envMap,
        envMapMode: material.envMap && material.envMap.mapping,
        envMapEncoding: getTextureEncodingFromMap(material.envMap, renderer.gammaInput),
        envMapCubeUV: (!!material.envMap) && ((material.envMap.mapping === THREE.CubeUVReflectionMapping) || (material.envMap.mapping === THREE.CubeUVRefractionMapping)),
        lightMap: !!material.lightMap,
        aoMap: !!material.aoMap,
        emissiveMap: !!material.emissiveMap,
        emissiveMapEncoding: getTextureEncodingFromMap(material.emissiveMap, renderer.gammaInput),
        bumpMap: !!material.bumpMap,
        normalMap: !!material.normalMap,
        displacementMap: !!material.displacementMap,
        roughnessMap: !!material.roughnessMap,
        metalnessMap: !!material.metalnessMap,
        specularMap: !!material.specularMap,
        alphaMap: !!material.alphaMap,
        combine: material.combine,
        vertexColors: material.vertexColors,
        fog: fog,
        useFog: material.fog,
        fogExp: fog instanceof THREE.FogExp2,
        flatShading: material.shading === THREE.FlatShading,
        sizeAttenuation: material.sizeAttenuation,
        logarithmicDepthBuffer: capabilities.logarithmicDepthBuffer,
        skinning: material.skinning,
        maxBones: maxBones,
        useVertexTexture: capabilities.floatVertexTextures && object && object.skeleton && object.skeleton.useVertexTexture,
        morphTargets: material.morphTargets,
        morphNormals: material.morphNormals,
        maxMorphTargets: renderer.maxMorphTargets,
        maxMorphNormals: renderer.maxMorphNormals,
        numDirLights: lights.directional.length,
        numPointLights: lights.point.length,
        numSpotLights: lights.spot.length,
        numHemiLights: lights.hemi.length,
        numClippingPlanes: nClipPlanes,
        shadowMapEnabled: renderer.shadowMap.enabled && object.receiveShadow && lights.shadows.length > 0,
        shadowMapType: renderer.shadowMap.type,
        toneMapping: renderer.toneMapping,
        physicallyCorrectLights: renderer.physicallyCorrectLights,
        premultipliedAlpha: material.premultipliedAlpha,
        alphaTest: material.alphaTest,
        doubleSided: material.side === THREE.DoubleSide,
        flipSided: material.side === THREE.BackSide,
        depthPacking: (material.depthPacking !== undefined) ? material.depthPacking : false
      };
      return parameters;
    };
    this.getProgramCode = function(material, parameters) {
      var array = [];
      if (parameters.shaderID) {
        array.push(parameters.shaderID);
      } else {
        array.push(material.fragmentShader);
        array.push(material.vertexShader);
      }
      if (material.defines !== undefined) {
        for (var name in material.defines) {
          array.push(name);
          array.push(material.defines[name]);
        }
      }
      for (var i = 0; i < parameterNames.length; i++) {
        array.push(parameters[parameterNames[i]]);
      }
      return array.join();
    };
    this.acquireProgram = function(material, parameters, code) {
      var program;
      for (var p = 0,
          pl = programs.length; p < pl; p++) {
        var programInfo = programs[p];
        if (programInfo.code === code) {
          program = programInfo;
          ++program.usedTimes;
          break;
        }
      }
      if (program === undefined) {
        program = new THREE.WebGLProgram(renderer, code, material, parameters);
        programs.push(program);
      }
      return program;
    };
    this.releaseProgram = function(program) {
      if (--program.usedTimes === 0) {
        var i = programs.indexOf(program);
        programs[i] = programs[programs.length - 1];
        programs.pop();
        program.destroy();
      }
    };
    this.programs = programs;
  };
  THREE.WebGLProperties = function() {
    var properties = {};
    this.get = function(object) {
      var uuid = object.uuid;
      var map = properties[uuid];
      if (map === undefined) {
        map = {};
        properties[uuid] = map;
      }
      return map;
    };
    this.delete = function(object) {
      delete properties[object.uuid];
    };
    this.clear = function() {
      properties = {};
    };
  };
  THREE.WebGLShader = (function() {
    function addLineNumbers(string) {
      var lines = string.split('\n');
      for (var i = 0; i < lines.length; i++) {
        lines[i] = (i + 1) + ': ' + lines[i];
      }
      return lines.join('\n');
    }
    return function WebGLShader(gl, type, string) {
      var shader = gl.createShader(type);
      gl.shaderSource(shader, string);
      gl.compileShader(shader);
      if (gl.getShaderParameter(shader, gl.COMPILE_STATUS) === false) {
        console.error('THREE.WebGLShader: Shader couldn\'t compile.');
      }
      if (gl.getShaderInfoLog(shader) !== '') {
        console.warn('THREE.WebGLShader: gl.getShaderInfoLog()', type === gl.VERTEX_SHADER ? 'vertex' : 'fragment', gl.getShaderInfoLog(shader), addLineNumbers(string));
      }
      return shader;
    };
  })();
  THREE.WebGLShadowMap = function(_renderer, _lights, _objects) {
    var _gl = _renderer.context,
        _state = _renderer.state,
        _frustum = new THREE.Frustum(),
        _projScreenMatrix = new THREE.Matrix4(),
        _lightShadows = _lights.shadows,
        _shadowMapSize = new THREE.Vector2(),
        _lookTarget = new THREE.Vector3(),
        _lightPositionWorld = new THREE.Vector3(),
        _renderList = [],
        _MorphingFlag = 1,
        _SkinningFlag = 2,
        _NumberOfMaterialVariants = (_MorphingFlag | _SkinningFlag) + 1,
        _depthMaterials = new Array(_NumberOfMaterialVariants),
        _distanceMaterials = new Array(_NumberOfMaterialVariants),
        _materialCache = {};
    var cubeDirections = [new THREE.Vector3(1, 0, 0), new THREE.Vector3(-1, 0, 0), new THREE.Vector3(0, 0, 1), new THREE.Vector3(0, 0, -1), new THREE.Vector3(0, 1, 0), new THREE.Vector3(0, -1, 0)];
    var cubeUps = [new THREE.Vector3(0, 1, 0), new THREE.Vector3(0, 1, 0), new THREE.Vector3(0, 1, 0), new THREE.Vector3(0, 1, 0), new THREE.Vector3(0, 0, 1), new THREE.Vector3(0, 0, -1)];
    var cube2DViewPorts = [new THREE.Vector4(), new THREE.Vector4(), new THREE.Vector4(), new THREE.Vector4(), new THREE.Vector4(), new THREE.Vector4()];
    var depthMaterialTemplate = new THREE.MeshDepthMaterial();
    depthMaterialTemplate.depthPacking = THREE.RGBADepthPacking;
    depthMaterialTemplate.clipping = true;
    var distanceShader = THREE.ShaderLib["distanceRGBA"];
    var distanceUniforms = THREE.UniformsUtils.clone(distanceShader.uniforms);
    for (var i = 0; i !== _NumberOfMaterialVariants; ++i) {
      var useMorphing = (i & _MorphingFlag) !== 0;
      var useSkinning = (i & _SkinningFlag) !== 0;
      var depthMaterial = depthMaterialTemplate.clone();
      depthMaterial.morphTargets = useMorphing;
      depthMaterial.skinning = useSkinning;
      _depthMaterials[i] = depthMaterial;
      var distanceMaterial = new THREE.ShaderMaterial({
        defines: {'USE_SHADOWMAP': ''},
        uniforms: distanceUniforms,
        vertexShader: distanceShader.vertexShader,
        fragmentShader: distanceShader.fragmentShader,
        morphTargets: useMorphing,
        skinning: useSkinning,
        clipping: true
      });
      _distanceMaterials[i] = distanceMaterial;
    }
    var scope = this;
    this.enabled = false;
    this.autoUpdate = true;
    this.needsUpdate = false;
    this.type = THREE.PCFShadowMap;
    this.renderReverseSided = true;
    this.renderSingleSided = true;
    this.render = function(scene, camera) {
      if (scope.enabled === false)
        return;
      if (scope.autoUpdate === false && scope.needsUpdate === false)
        return;
      if (_lightShadows.length === 0)
        return;
      _state.clearColor(1, 1, 1, 1);
      _state.disable(_gl.BLEND);
      _state.setDepthTest(true);
      _state.setScissorTest(false);
      var faceCount,
          isPointLight;
      for (var i = 0,
          il = _lightShadows.length; i < il; i++) {
        var light = _lightShadows[i];
        var shadow = light.shadow;
        if (shadow === undefined) {
          console.warn('THREE.WebGLShadowMap:', light, 'has no shadow.');
          continue;
        }
        var shadowCamera = shadow.camera;
        _shadowMapSize.copy(shadow.mapSize);
        if (light instanceof THREE.PointLight) {
          faceCount = 6;
          isPointLight = true;
          var vpWidth = _shadowMapSize.x;
          var vpHeight = _shadowMapSize.y;
          cube2DViewPorts[0].set(vpWidth * 2, vpHeight, vpWidth, vpHeight);
          cube2DViewPorts[1].set(0, vpHeight, vpWidth, vpHeight);
          cube2DViewPorts[2].set(vpWidth * 3, vpHeight, vpWidth, vpHeight);
          cube2DViewPorts[3].set(vpWidth, vpHeight, vpWidth, vpHeight);
          cube2DViewPorts[4].set(vpWidth * 3, 0, vpWidth, vpHeight);
          cube2DViewPorts[5].set(vpWidth, 0, vpWidth, vpHeight);
          _shadowMapSize.x *= 4.0;
          _shadowMapSize.y *= 2.0;
        } else {
          faceCount = 1;
          isPointLight = false;
        }
        if (shadow.map === null) {
          var pars = {
            minFilter: THREE.NearestFilter,
            magFilter: THREE.NearestFilter,
            format: THREE.RGBAFormat
          };
          shadow.map = new THREE.WebGLRenderTarget(_shadowMapSize.x, _shadowMapSize.y, pars);
          shadowCamera.updateProjectionMatrix();
        }
        if (shadow instanceof THREE.SpotLightShadow) {
          shadow.update(light);
        }
        var shadowMap = shadow.map;
        var shadowMatrix = shadow.matrix;
        _lightPositionWorld.setFromMatrixPosition(light.matrixWorld);
        shadowCamera.position.copy(_lightPositionWorld);
        _renderer.setRenderTarget(shadowMap);
        _renderer.clear();
        for (var face = 0; face < faceCount; face++) {
          if (isPointLight) {
            _lookTarget.copy(shadowCamera.position);
            _lookTarget.add(cubeDirections[face]);
            shadowCamera.up.copy(cubeUps[face]);
            shadowCamera.lookAt(_lookTarget);
            var vpDimensions = cube2DViewPorts[face];
            _state.viewport(vpDimensions);
          } else {
            _lookTarget.setFromMatrixPosition(light.target.matrixWorld);
            shadowCamera.lookAt(_lookTarget);
          }
          shadowCamera.updateMatrixWorld();
          shadowCamera.matrixWorldInverse.getInverse(shadowCamera.matrixWorld);
          shadowMatrix.set(0.5, 0.0, 0.0, 0.5, 0.0, 0.5, 0.0, 0.5, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.0, 1.0);
          shadowMatrix.multiply(shadowCamera.projectionMatrix);
          shadowMatrix.multiply(shadowCamera.matrixWorldInverse);
          _projScreenMatrix.multiplyMatrices(shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse);
          _frustum.setFromMatrix(_projScreenMatrix);
          _renderList.length = 0;
          projectObject(scene, camera, shadowCamera);
          for (var j = 0,
              jl = _renderList.length; j < jl; j++) {
            var object = _renderList[j];
            var geometry = _objects.update(object);
            var material = object.material;
            if (material instanceof THREE.MultiMaterial) {
              var groups = geometry.groups;
              var materials = material.materials;
              for (var k = 0,
                  kl = groups.length; k < kl; k++) {
                var group = groups[k];
                var groupMaterial = materials[group.materialIndex];
                if (groupMaterial.visible === true) {
                  var depthMaterial = getDepthMaterial(object, groupMaterial, isPointLight, _lightPositionWorld);
                  _renderer.renderBufferDirect(shadowCamera, null, geometry, depthMaterial, object, group);
                }
              }
            } else {
              var depthMaterial = getDepthMaterial(object, material, isPointLight, _lightPositionWorld);
              _renderer.renderBufferDirect(shadowCamera, null, geometry, depthMaterial, object, null);
            }
          }
        }
      }
      var clearColor = _renderer.getClearColor(),
          clearAlpha = _renderer.getClearAlpha();
      _renderer.setClearColor(clearColor, clearAlpha);
      scope.needsUpdate = false;
    };
    function getDepthMaterial(object, material, isPointLight, lightPositionWorld) {
      var geometry = object.geometry;
      var result = null;
      var materialVariants = _depthMaterials;
      var customMaterial = object.customDepthMaterial;
      if (isPointLight) {
        materialVariants = _distanceMaterials;
        customMaterial = object.customDistanceMaterial;
      }
      if (!customMaterial) {
        var useMorphing = geometry.morphTargets !== undefined && geometry.morphTargets.length > 0 && material.morphTargets;
        var useSkinning = object instanceof THREE.SkinnedMesh && material.skinning;
        var variantIndex = 0;
        if (useMorphing)
          variantIndex |= _MorphingFlag;
        if (useSkinning)
          variantIndex |= _SkinningFlag;
        result = materialVariants[variantIndex];
      } else {
        result = customMaterial;
      }
      if (_renderer.localClippingEnabled && material.clipShadows === true && material.clippingPlanes.length !== 0) {
        var keyA = result.uuid,
            keyB = material.uuid;
        var materialsForVariant = _materialCache[keyA];
        if (materialsForVariant === undefined) {
          materialsForVariant = {};
          _materialCache[keyA] = materialsForVariant;
        }
        var cachedMaterial = materialsForVariant[keyB];
        if (cachedMaterial === undefined) {
          cachedMaterial = result.clone();
          materialsForVariant[keyB] = cachedMaterial;
        }
        result = cachedMaterial;
      }
      result.visible = material.visible;
      result.wireframe = material.wireframe;
      var side = material.side;
      if (scope.renderSingleSided && side == THREE.DoubleSide) {
        side = THREE.FrontSide;
      }
      if (scope.renderReverseSided) {
        if (side === THREE.FrontSide)
          side = THREE.BackSide;
        else if (side === THREE.BackSide)
          side = THREE.FrontSide;
      }
      result.side = side;
      result.clipShadows = material.clipShadows;
      result.clippingPlanes = material.clippingPlanes;
      result.wireframeLinewidth = material.wireframeLinewidth;
      result.linewidth = material.linewidth;
      if (isPointLight && result.uniforms.lightPos !== undefined) {
        result.uniforms.lightPos.value.copy(lightPositionWorld);
      }
      return result;
    }
    function projectObject(object, camera, shadowCamera) {
      if (object.visible === false)
        return;
      if (object.layers.test(camera.layers) && (object instanceof THREE.Mesh || object instanceof THREE.Line || object instanceof THREE.Points)) {
        if (object.castShadow && (object.frustumCulled === false || _frustum.intersectsObject(object) === true)) {
          var material = object.material;
          if (material.visible === true) {
            object.modelViewMatrix.multiplyMatrices(shadowCamera.matrixWorldInverse, object.matrixWorld);
            _renderList.push(object);
          }
        }
      }
      var children = object.children;
      for (var i = 0,
          l = children.length; i < l; i++) {
        projectObject(children[i], camera, shadowCamera);
      }
    }
  };
  THREE.WebGLState = function(gl, extensions, paramThreeToGL) {
    var _this = this;
    this.buffers = {
      color: new THREE.WebGLColorBuffer(gl, this),
      depth: new THREE.WebGLDepthBuffer(gl, this),
      stencil: new THREE.WebGLStencilBuffer(gl, this)
    };
    var maxVertexAttributes = gl.getParameter(gl.MAX_VERTEX_ATTRIBS);
    var newAttributes = new Uint8Array(maxVertexAttributes);
    var enabledAttributes = new Uint8Array(maxVertexAttributes);
    var attributeDivisors = new Uint8Array(maxVertexAttributes);
    var capabilities = {};
    var compressedTextureFormats = null;
    var currentBlending = null;
    var currentBlendEquation = null;
    var currentBlendSrc = null;
    var currentBlendDst = null;
    var currentBlendEquationAlpha = null;
    var currentBlendSrcAlpha = null;
    var currentBlendDstAlpha = null;
    var currentPremultipledAlpha = false;
    var currentFlipSided = null;
    var currentCullFace = null;
    var currentLineWidth = null;
    var currentPolygonOffsetFactor = null;
    var currentPolygonOffsetUnits = null;
    var currentScissorTest = null;
    var maxTextures = gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS);
    var currentTextureSlot = null;
    var currentBoundTextures = {};
    var currentScissor = new THREE.Vector4();
    var currentViewport = new THREE.Vector4();
    function createTexture(type, target, count) {
      var data = new Uint8Array(4);
      var texture = gl.createTexture();
      gl.bindTexture(type, texture);
      gl.texParameteri(type, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
      gl.texParameteri(type, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
      for (var i = 0; i < count; i++) {
        gl.texImage2D(target + i, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, data);
      }
      return texture;
    }
    var emptyTextures = {};
    emptyTextures[gl.TEXTURE_2D] = createTexture(gl.TEXTURE_2D, gl.TEXTURE_2D, 1);
    emptyTextures[gl.TEXTURE_CUBE_MAP] = createTexture(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_CUBE_MAP_POSITIVE_X, 6);
    this.init = function() {
      this.clearColor(0, 0, 0, 1);
      this.clearDepth(1);
      this.clearStencil(0);
      this.enable(gl.DEPTH_TEST);
      this.setDepthFunc(THREE.LessEqualDepth);
      this.setFlipSided(false);
      this.setCullFace(THREE.CullFaceBack);
      this.enable(gl.CULL_FACE);
      this.enable(gl.BLEND);
      this.setBlending(THREE.NormalBlending);
    };
    this.initAttributes = function() {
      for (var i = 0,
          l = newAttributes.length; i < l; i++) {
        newAttributes[i] = 0;
      }
    };
    this.enableAttribute = function(attribute) {
      newAttributes[attribute] = 1;
      if (enabledAttributes[attribute] === 0) {
        gl.enableVertexAttribArray(attribute);
        enabledAttributes[attribute] = 1;
      }
      if (attributeDivisors[attribute] !== 0) {
        var extension = extensions.get('ANGLE_instanced_arrays');
        extension.vertexAttribDivisorANGLE(attribute, 0);
        attributeDivisors[attribute] = 0;
      }
    };
    this.enableAttributeAndDivisor = function(attribute, meshPerAttribute, extension) {
      newAttributes[attribute] = 1;
      if (enabledAttributes[attribute] === 0) {
        gl.enableVertexAttribArray(attribute);
        enabledAttributes[attribute] = 1;
      }
      if (attributeDivisors[attribute] !== meshPerAttribute) {
        extension.vertexAttribDivisorANGLE(attribute, meshPerAttribute);
        attributeDivisors[attribute] = meshPerAttribute;
      }
    };
    this.disableUnusedAttributes = function() {
      for (var i = 0,
          l = enabledAttributes.length; i !== l; ++i) {
        if (enabledAttributes[i] !== newAttributes[i]) {
          gl.disableVertexAttribArray(i);
          enabledAttributes[i] = 0;
        }
      }
    };
    this.enable = function(id) {
      if (capabilities[id] !== true) {
        gl.enable(id);
        capabilities[id] = true;
      }
    };
    this.disable = function(id) {
      if (capabilities[id] !== false) {
        gl.disable(id);
        capabilities[id] = false;
      }
    };
    this.getCompressedTextureFormats = function() {
      if (compressedTextureFormats === null) {
        compressedTextureFormats = [];
        if (extensions.get('WEBGL_compressed_texture_pvrtc') || extensions.get('WEBGL_compressed_texture_s3tc') || extensions.get('WEBGL_compressed_texture_etc1')) {
          var formats = gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS);
          for (var i = 0; i < formats.length; i++) {
            compressedTextureFormats.push(formats[i]);
          }
        }
      }
      return compressedTextureFormats;
    };
    this.setBlending = function(blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, premultipliedAlpha) {
      if (blending !== THREE.NoBlending) {
        this.enable(gl.BLEND);
      } else {
        this.disable(gl.BLEND);
        currentBlending = blending;
        return;
      }
      if (blending !== currentBlending || premultipliedAlpha !== currentPremultipledAlpha) {
        if (blending === THREE.AdditiveBlending) {
          if (premultipliedAlpha) {
            gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD);
            gl.blendFuncSeparate(gl.ONE, gl.ONE, gl.ONE, gl.ONE);
          } else {
            gl.blendEquation(gl.FUNC_ADD);
            gl.blendFunc(gl.SRC_ALPHA, gl.ONE);
          }
        } else if (blending === THREE.SubtractiveBlending) {
          if (premultipliedAlpha) {
            gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD);
            gl.blendFuncSeparate(gl.ZERO, gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ONE_MINUS_SRC_ALPHA);
          } else {
            gl.blendEquation(gl.FUNC_ADD);
            gl.blendFunc(gl.ZERO, gl.ONE_MINUS_SRC_COLOR);
          }
        } else if (blending === THREE.MultiplyBlending) {
          if (premultipliedAlpha) {
            gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD);
            gl.blendFuncSeparate(gl.ZERO, gl.SRC_COLOR, gl.ZERO, gl.SRC_ALPHA);
          } else {
            gl.blendEquation(gl.FUNC_ADD);
            gl.blendFunc(gl.ZERO, gl.SRC_COLOR);
          }
        } else {
          if (premultipliedAlpha) {
            gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD);
            gl.blendFuncSeparate(gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
          } else {
            gl.blendEquationSeparate(gl.FUNC_ADD, gl.FUNC_ADD);
            gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
          }
        }
        currentBlending = blending;
        currentPremultipledAlpha = premultipliedAlpha;
      }
      if (blending === THREE.CustomBlending) {
        blendEquationAlpha = blendEquationAlpha || blendEquation;
        blendSrcAlpha = blendSrcAlpha || blendSrc;
        blendDstAlpha = blendDstAlpha || blendDst;
        if (blendEquation !== currentBlendEquation || blendEquationAlpha !== currentBlendEquationAlpha) {
          gl.blendEquationSeparate(paramThreeToGL(blendEquation), paramThreeToGL(blendEquationAlpha));
          currentBlendEquation = blendEquation;
          currentBlendEquationAlpha = blendEquationAlpha;
        }
        if (blendSrc !== currentBlendSrc || blendDst !== currentBlendDst || blendSrcAlpha !== currentBlendSrcAlpha || blendDstAlpha !== currentBlendDstAlpha) {
          gl.blendFuncSeparate(paramThreeToGL(blendSrc), paramThreeToGL(blendDst), paramThreeToGL(blendSrcAlpha), paramThreeToGL(blendDstAlpha));
          currentBlendSrc = blendSrc;
          currentBlendDst = blendDst;
          currentBlendSrcAlpha = blendSrcAlpha;
          currentBlendDstAlpha = blendDstAlpha;
        }
      } else {
        currentBlendEquation = null;
        currentBlendSrc = null;
        currentBlendDst = null;
        currentBlendEquationAlpha = null;
        currentBlendSrcAlpha = null;
        currentBlendDstAlpha = null;
      }
    };
    this.setColorWrite = function(colorWrite) {
      this.buffers.color.setMask(colorWrite);
    };
    this.setDepthTest = function(depthTest) {
      this.buffers.depth.setTest(depthTest);
    };
    this.setDepthWrite = function(depthWrite) {
      this.buffers.depth.setMask(depthWrite);
    };
    this.setDepthFunc = function(depthFunc) {
      this.buffers.depth.setFunc(depthFunc);
    };
    this.setStencilTest = function(stencilTest) {
      this.buffers.stencil.setTest(stencilTest);
    };
    this.setStencilWrite = function(stencilWrite) {
      this.buffers.stencil.setMask(stencilWrite);
    };
    this.setStencilFunc = function(stencilFunc, stencilRef, stencilMask) {
      this.buffers.stencil.setFunc(stencilFunc, stencilRef, stencilMask);
    };
    this.setStencilOp = function(stencilFail, stencilZFail, stencilZPass) {
      this.buffers.stencil.setOp(stencilFail, stencilZFail, stencilZPass);
    };
    this.setFlipSided = function(flipSided) {
      if (currentFlipSided !== flipSided) {
        if (flipSided) {
          gl.frontFace(gl.CW);
        } else {
          gl.frontFace(gl.CCW);
        }
        currentFlipSided = flipSided;
      }
    };
    this.setCullFace = function(cullFace) {
      if (cullFace !== THREE.CullFaceNone) {
        this.enable(gl.CULL_FACE);
        if (cullFace !== currentCullFace) {
          if (cullFace === THREE.CullFaceBack) {
            gl.cullFace(gl.BACK);
          } else if (cullFace === THREE.CullFaceFront) {
            gl.cullFace(gl.FRONT);
          } else {
            gl.cullFace(gl.FRONT_AND_BACK);
          }
        }
      } else {
        this.disable(gl.CULL_FACE);
      }
      currentCullFace = cullFace;
    };
    this.setLineWidth = function(width) {
      if (width !== currentLineWidth) {
        gl.lineWidth(width);
        currentLineWidth = width;
      }
    };
    this.setPolygonOffset = function(polygonOffset, factor, units) {
      if (polygonOffset) {
        this.enable(gl.POLYGON_OFFSET_FILL);
        if (currentPolygonOffsetFactor !== factor || currentPolygonOffsetUnits !== units) {
          gl.polygonOffset(factor, units);
          currentPolygonOffsetFactor = factor;
          currentPolygonOffsetUnits = units;
        }
      } else {
        this.disable(gl.POLYGON_OFFSET_FILL);
      }
    };
    this.getScissorTest = function() {
      return currentScissorTest;
    };
    this.setScissorTest = function(scissorTest) {
      currentScissorTest = scissorTest;
      if (scissorTest) {
        this.enable(gl.SCISSOR_TEST);
      } else {
        this.disable(gl.SCISSOR_TEST);
      }
    };
    this.activeTexture = function(webglSlot) {
      if (webglSlot === undefined)
        webglSlot = gl.TEXTURE0 + maxTextures - 1;
      if (currentTextureSlot !== webglSlot) {
        gl.activeTexture(webglSlot);
        currentTextureSlot = webglSlot;
      }
    };
    this.bindTexture = function(webglType, webglTexture) {
      if (currentTextureSlot === null) {
        _this.activeTexture();
      }
      var boundTexture = currentBoundTextures[currentTextureSlot];
      if (boundTexture === undefined) {
        boundTexture = {
          type: undefined,
          texture: undefined
        };
        currentBoundTextures[currentTextureSlot] = boundTexture;
      }
      if (boundTexture.type !== webglType || boundTexture.texture !== webglTexture) {
        gl.bindTexture(webglType, webglTexture || emptyTextures[webglType]);
        boundTexture.type = webglType;
        boundTexture.texture = webglTexture;
      }
    };
    this.compressedTexImage2D = function() {
      try {
        gl.compressedTexImage2D.apply(gl, arguments);
      } catch (error) {
        console.error(error);
      }
    };
    this.texImage2D = function() {
      try {
        gl.texImage2D.apply(gl, arguments);
      } catch (error) {
        console.error(error);
      }
    };
    this.clearColor = function(r, g, b, a) {
      this.buffers.color.setClear(r, g, b, a);
    };
    this.clearDepth = function(depth) {
      this.buffers.depth.setClear(depth);
    };
    this.clearStencil = function(stencil) {
      this.buffers.stencil.setClear(stencil);
    };
    this.scissor = function(scissor) {
      if (currentScissor.equals(scissor) === false) {
        gl.scissor(scissor.x, scissor.y, scissor.z, scissor.w);
        currentScissor.copy(scissor);
      }
    };
    this.viewport = function(viewport) {
      if (currentViewport.equals(viewport) === false) {
        gl.viewport(viewport.x, viewport.y, viewport.z, viewport.w);
        currentViewport.copy(viewport);
      }
    };
    this.reset = function() {
      for (var i = 0; i < enabledAttributes.length; i++) {
        if (enabledAttributes[i] === 1) {
          gl.disableVertexAttribArray(i);
          enabledAttributes[i] = 0;
        }
      }
      capabilities = {};
      compressedTextureFormats = null;
      currentTextureSlot = null;
      currentBoundTextures = {};
      currentBlending = null;
      currentFlipSided = null;
      currentCullFace = null;
      this.buffers.color.reset();
      this.buffers.depth.reset();
      this.buffers.stencil.reset();
    };
  };
  THREE.WebGLColorBuffer = function(gl, state) {
    var locked = false;
    var color = new THREE.Vector4();
    var currentColorMask = null;
    var currentColorClear = new THREE.Vector4();
    this.setMask = function(colorMask) {
      if (currentColorMask !== colorMask && !locked) {
        gl.colorMask(colorMask, colorMask, colorMask, colorMask);
        currentColorMask = colorMask;
      }
    };
    this.setLocked = function(lock) {
      locked = lock;
    };
    this.setClear = function(r, g, b, a) {
      color.set(r, g, b, a);
      if (currentColorClear.equals(color) === false) {
        gl.clearColor(r, g, b, a);
        currentColorClear.copy(color);
      }
    };
    this.reset = function() {
      locked = false;
      currentColorMask = null;
      currentColorClear = new THREE.Vector4();
    };
  };
  THREE.WebGLDepthBuffer = function(gl, state) {
    var locked = false;
    var currentDepthMask = null;
    var currentDepthFunc = null;
    var currentDepthClear = null;
    this.setTest = function(depthTest) {
      if (depthTest) {
        state.enable(gl.DEPTH_TEST);
      } else {
        state.disable(gl.DEPTH_TEST);
      }
    };
    this.setMask = function(depthMask) {
      if (currentDepthMask !== depthMask && !locked) {
        gl.depthMask(depthMask);
        currentDepthMask = depthMask;
      }
    };
    this.setFunc = function(depthFunc) {
      if (currentDepthFunc !== depthFunc) {
        if (depthFunc) {
          switch (depthFunc) {
            case THREE.NeverDepth:
              gl.depthFunc(gl.NEVER);
              break;
            case THREE.AlwaysDepth:
              gl.depthFunc(gl.ALWAYS);
              break;
            case THREE.LessDepth:
              gl.depthFunc(gl.LESS);
              break;
            case THREE.LessEqualDepth:
              gl.depthFunc(gl.LEQUAL);
              break;
            case THREE.EqualDepth:
              gl.depthFunc(gl.EQUAL);
              break;
            case THREE.GreaterEqualDepth:
              gl.depthFunc(gl.GEQUAL);
              break;
            case THREE.GreaterDepth:
              gl.depthFunc(gl.GREATER);
              break;
            case THREE.NotEqualDepth:
              gl.depthFunc(gl.NOTEQUAL);
              break;
            default:
              gl.depthFunc(gl.LEQUAL);
          }
        } else {
          gl.depthFunc(gl.LEQUAL);
        }
        currentDepthFunc = depthFunc;
      }
    };
    this.setLocked = function(lock) {
      locked = lock;
    };
    this.setClear = function(depth) {
      if (currentDepthClear !== depth) {
        gl.clearDepth(depth);
        currentDepthClear = depth;
      }
    };
    this.reset = function() {
      locked = false;
      currentDepthMask = null;
      currentDepthFunc = null;
      currentDepthClear = null;
    };
  };
  THREE.WebGLStencilBuffer = function(gl, state) {
    var locked = false;
    var currentStencilMask = null;
    var currentStencilFunc = null;
    var currentStencilRef = null;
    var currentStencilFuncMask = null;
    var currentStencilFail = null;
    var currentStencilZFail = null;
    var currentStencilZPass = null;
    var currentStencilClear = null;
    this.setTest = function(stencilTest) {
      if (stencilTest) {
        state.enable(gl.STENCIL_TEST);
      } else {
        state.disable(gl.STENCIL_TEST);
      }
    };
    this.setMask = function(stencilMask) {
      if (currentStencilMask !== stencilMask && !locked) {
        gl.stencilMask(stencilMask);
        currentStencilMask = stencilMask;
      }
    };
    this.setFunc = function(stencilFunc, stencilRef, stencilMask) {
      if (currentStencilFunc !== stencilFunc || currentStencilRef !== stencilRef || currentStencilFuncMask !== stencilMask) {
        gl.stencilFunc(stencilFunc, stencilRef, stencilMask);
        currentStencilFunc = stencilFunc;
        currentStencilRef = stencilRef;
        currentStencilFuncMask = stencilMask;
      }
    };
    this.setOp = function(stencilFail, stencilZFail, stencilZPass) {
      if (currentStencilFail !== stencilFail || currentStencilZFail !== stencilZFail || currentStencilZPass !== stencilZPass) {
        gl.stencilOp(stencilFail, stencilZFail, stencilZPass);
        currentStencilFail = stencilFail;
        currentStencilZFail = stencilZFail;
        currentStencilZPass = stencilZPass;
      }
    };
    this.setLocked = function(lock) {
      locked = lock;
    };
    this.setClear = function(stencil) {
      if (currentStencilClear !== stencil) {
        gl.clearStencil(stencil);
        currentStencilClear = stencil;
      }
    };
    this.reset = function() {
      locked = false;
      currentStencilMask = null;
      currentStencilFunc = null;
      currentStencilRef = null;
      currentStencilFuncMask = null;
      currentStencilFail = null;
      currentStencilZFail = null;
      currentStencilZPass = null;
      currentStencilClear = null;
    };
  };
  THREE.WebGLTextures = function(_gl, extensions, state, properties, capabilities, paramThreeToGL, info) {
    var _infoMemory = info.memory;
    var _isWebGL2 = (typeof WebGL2RenderingContext !== 'undefined' && _gl instanceof WebGL2RenderingContext);
    function clampToMaxSize(image, maxSize) {
      if (image.width > maxSize || image.height > maxSize) {
        var scale = maxSize / Math.max(image.width, image.height);
        var canvas = document.createElementNS('http://www.w3.org/1999/xhtml', 'canvas');
        canvas.width = Math.floor(image.width * scale);
        canvas.height = Math.floor(image.height * scale);
        var context = canvas.getContext('2d');
        context.drawImage(image, 0, 0, image.width, image.height, 0, 0, canvas.width, canvas.height);
        console.warn('THREE.WebGLRenderer: image is too big (' + image.width + 'x' + image.height + '). Resized to ' + canvas.width + 'x' + canvas.height, image);
        return canvas;
      }
      return image;
    }
    function isPowerOfTwo(image) {
      return THREE.Math.isPowerOfTwo(image.width) && THREE.Math.isPowerOfTwo(image.height);
    }
    function makePowerOfTwo(image) {
      if (image instanceof HTMLImageElement || image instanceof HTMLCanvasElement) {
        var canvas = document.createElementNS('http://www.w3.org/1999/xhtml', 'canvas');
        canvas.width = THREE.Math.nearestPowerOfTwo(image.width);
        canvas.height = THREE.Math.nearestPowerOfTwo(image.height);
        var context = canvas.getContext('2d');
        context.drawImage(image, 0, 0, canvas.width, canvas.height);
        console.warn('THREE.WebGLRenderer: image is not power of two (' + image.width + 'x' + image.height + '). Resized to ' + canvas.width + 'x' + canvas.height, image);
        return canvas;
      }
      return image;
    }
    function textureNeedsPowerOfTwo(texture) {
      if (texture.wrapS !== THREE.ClampToEdgeWrapping || texture.wrapT !== THREE.ClampToEdgeWrapping)
        return true;
      if (texture.minFilter !== THREE.NearestFilter && texture.minFilter !== THREE.LinearFilter)
        return true;
      return false;
    }
    function filterFallback(f) {
      if (f === THREE.NearestFilter || f === THREE.NearestMipMapNearestFilter || f === THREE.NearestMipMapLinearFilter) {
        return _gl.NEAREST;
      }
      return _gl.LINEAR;
    }
    function onTextureDispose(event) {
      var texture = event.target;
      texture.removeEventListener('dispose', onTextureDispose);
      deallocateTexture(texture);
      _infoMemory.textures--;
    }
    function onRenderTargetDispose(event) {
      var renderTarget = event.target;
      renderTarget.removeEventListener('dispose', onRenderTargetDispose);
      deallocateRenderTarget(renderTarget);
      _infoMemory.textures--;
    }
    function deallocateTexture(texture) {
      var textureProperties = properties.get(texture);
      if (texture.image && textureProperties.__image__webglTextureCube) {
        _gl.deleteTexture(textureProperties.__image__webglTextureCube);
      } else {
        if (textureProperties.__webglInit === undefined)
          return;
        _gl.deleteTexture(textureProperties.__webglTexture);
      }
      properties.delete(texture);
    }
    function deallocateRenderTarget(renderTarget) {
      var renderTargetProperties = properties.get(renderTarget);
      var textureProperties = properties.get(renderTarget.texture);
      if (!renderTarget)
        return;
      if (textureProperties.__webglTexture !== undefined) {
        _gl.deleteTexture(textureProperties.__webglTexture);
      }
      if (renderTarget.depthTexture) {
        renderTarget.depthTexture.dispose();
      }
      if (renderTarget instanceof THREE.WebGLRenderTargetCube) {
        for (var i = 0; i < 6; i++) {
          _gl.deleteFramebuffer(renderTargetProperties.__webglFramebuffer[i]);
          if (renderTargetProperties.__webglDepthbuffer)
            _gl.deleteRenderbuffer(renderTargetProperties.__webglDepthbuffer[i]);
        }
      } else {
        _gl.deleteFramebuffer(renderTargetProperties.__webglFramebuffer);
        if (renderTargetProperties.__webglDepthbuffer)
          _gl.deleteRenderbuffer(renderTargetProperties.__webglDepthbuffer);
      }
      properties.delete(renderTarget.texture);
      properties.delete(renderTarget);
    }
    function setTexture2D(texture, slot) {
      var textureProperties = properties.get(texture);
      if (texture.version > 0 && textureProperties.__version !== texture.version) {
        var image = texture.image;
        if (image === undefined) {
          console.warn('THREE.WebGLRenderer: Texture marked for update but image is undefined', texture);
        } else if (image.complete === false) {
          console.warn('THREE.WebGLRenderer: Texture marked for update but image is incomplete', texture);
        } else {
          uploadTexture(textureProperties, texture, slot);
          return;
        }
      }
      state.activeTexture(_gl.TEXTURE0 + slot);
      state.bindTexture(_gl.TEXTURE_2D, textureProperties.__webglTexture);
    }
    function setTextureCube(texture, slot) {
      var textureProperties = properties.get(texture);
      if (texture.image.length === 6) {
        if (texture.version > 0 && textureProperties.__version !== texture.version) {
          if (!textureProperties.__image__webglTextureCube) {
            texture.addEventListener('dispose', onTextureDispose);
            textureProperties.__image__webglTextureCube = _gl.createTexture();
            _infoMemory.textures++;
          }
          state.activeTexture(_gl.TEXTURE0 + slot);
          state.bindTexture(_gl.TEXTURE_CUBE_MAP, textureProperties.__image__webglTextureCube);
          _gl.pixelStorei(_gl.UNPACK_FLIP_Y_WEBGL, texture.flipY);
          var isCompressed = texture instanceof THREE.CompressedTexture;
          var isDataTexture = texture.image[0] instanceof THREE.DataTexture;
          var cubeImage = [];
          for (var i = 0; i < 6; i++) {
            if (!isCompressed && !isDataTexture) {
              cubeImage[i] = clampToMaxSize(texture.image[i], capabilities.maxCubemapSize);
            } else {
              cubeImage[i] = isDataTexture ? texture.image[i].image : texture.image[i];
            }
          }
          var image = cubeImage[0],
              isPowerOfTwoImage = isPowerOfTwo(image),
              glFormat = paramThreeToGL(texture.format),
              glType = paramThreeToGL(texture.type);
          setTextureParameters(_gl.TEXTURE_CUBE_MAP, texture, isPowerOfTwoImage);
          for (var i = 0; i < 6; i++) {
            if (!isCompressed) {
              if (isDataTexture) {
                state.texImage2D(_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, cubeImage[i].width, cubeImage[i].height, 0, glFormat, glType, cubeImage[i].data);
              } else {
                state.texImage2D(_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, glFormat, glType, cubeImage[i]);
              }
            } else {
              var mipmap,
                  mipmaps = cubeImage[i].mipmaps;
              for (var j = 0,
                  jl = mipmaps.length; j < jl; j++) {
                mipmap = mipmaps[j];
                if (texture.format !== THREE.RGBAFormat && texture.format !== THREE.RGBFormat) {
                  if (state.getCompressedTextureFormats().indexOf(glFormat) > -1) {
                    state.compressedTexImage2D(_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, mipmap.data);
                  } else {
                    console.warn("THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()");
                  }
                } else {
                  state.texImage2D(_gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data);
                }
              }
            }
          }
          if (texture.generateMipmaps && isPowerOfTwoImage) {
            _gl.generateMipmap(_gl.TEXTURE_CUBE_MAP);
          }
          textureProperties.__version = texture.version;
          if (texture.onUpdate)
            texture.onUpdate(texture);
        } else {
          state.activeTexture(_gl.TEXTURE0 + slot);
          state.bindTexture(_gl.TEXTURE_CUBE_MAP, textureProperties.__image__webglTextureCube);
        }
      }
    }
    function setTextureCubeDynamic(texture, slot) {
      state.activeTexture(_gl.TEXTURE0 + slot);
      state.bindTexture(_gl.TEXTURE_CUBE_MAP, properties.get(texture).__webglTexture);
    }
    function setTextureParameters(textureType, texture, isPowerOfTwoImage) {
      var extension;
      if (isPowerOfTwoImage) {
        _gl.texParameteri(textureType, _gl.TEXTURE_WRAP_S, paramThreeToGL(texture.wrapS));
        _gl.texParameteri(textureType, _gl.TEXTURE_WRAP_T, paramThreeToGL(texture.wrapT));
        _gl.texParameteri(textureType, _gl.TEXTURE_MAG_FILTER, paramThreeToGL(texture.magFilter));
        _gl.texParameteri(textureType, _gl.TEXTURE_MIN_FILTER, paramThreeToGL(texture.minFilter));
      } else {
        _gl.texParameteri(textureType, _gl.TEXTURE_WRAP_S, _gl.CLAMP_TO_EDGE);
        _gl.texParameteri(textureType, _gl.TEXTURE_WRAP_T, _gl.CLAMP_TO_EDGE);
        if (texture.wrapS !== THREE.ClampToEdgeWrapping || texture.wrapT !== THREE.ClampToEdgeWrapping) {
          console.warn('THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping.', texture);
        }
        _gl.texParameteri(textureType, _gl.TEXTURE_MAG_FILTER, filterFallback(texture.magFilter));
        _gl.texParameteri(textureType, _gl.TEXTURE_MIN_FILTER, filterFallback(texture.minFilter));
        if (texture.minFilter !== THREE.NearestFilter && texture.minFilter !== THREE.LinearFilter) {
          console.warn('THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter.', texture);
        }
      }
      extension = extensions.get('EXT_texture_filter_anisotropic');
      if (extension) {
        if (texture.type === THREE.FloatType && extensions.get('OES_texture_float_linear') === null)
          return;
        if (texture.type === THREE.HalfFloatType && extensions.get('OES_texture_half_float_linear') === null)
          return;
        if (texture.anisotropy > 1 || properties.get(texture).__currentAnisotropy) {
          _gl.texParameterf(textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min(texture.anisotropy, capabilities.getMaxAnisotropy()));
          properties.get(texture).__currentAnisotropy = texture.anisotropy;
        }
      }
    }
    function uploadTexture(textureProperties, texture, slot) {
      if (textureProperties.__webglInit === undefined) {
        textureProperties.__webglInit = true;
        texture.addEventListener('dispose', onTextureDispose);
        textureProperties.__webglTexture = _gl.createTexture();
        _infoMemory.textures++;
      }
      state.activeTexture(_gl.TEXTURE0 + slot);
      state.bindTexture(_gl.TEXTURE_2D, textureProperties.__webglTexture);
      _gl.pixelStorei(_gl.UNPACK_FLIP_Y_WEBGL, texture.flipY);
      _gl.pixelStorei(_gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha);
      _gl.pixelStorei(_gl.UNPACK_ALIGNMENT, texture.unpackAlignment);
      var image = clampToMaxSize(texture.image, capabilities.maxTextureSize);
      if (textureNeedsPowerOfTwo(texture) && isPowerOfTwo(image) === false) {
        image = makePowerOfTwo(image);
      }
      var isPowerOfTwoImage = isPowerOfTwo(image),
          glFormat = paramThreeToGL(texture.format),
          glType = paramThreeToGL(texture.type);
      setTextureParameters(_gl.TEXTURE_2D, texture, isPowerOfTwoImage);
      var mipmap,
          mipmaps = texture.mipmaps;
      if (texture instanceof THREE.DepthTexture) {
        var internalFormat = _gl.DEPTH_COMPONENT;
        if (texture.type === THREE.FloatType) {
          if (!_isWebGL2)
            throw new Error('Float Depth Texture only supported in WebGL2.0');
          internalFormat = _gl.DEPTH_COMPONENT32F;
        } else if (_isWebGL2) {
          internalFormat = _gl.DEPTH_COMPONENT16;
        }
        state.texImage2D(_gl.TEXTURE_2D, 0, internalFormat, image.width, image.height, 0, glFormat, glType, null);
      } else if (texture instanceof THREE.DataTexture) {
        if (mipmaps.length > 0 && isPowerOfTwoImage) {
          for (var i = 0,
              il = mipmaps.length; i < il; i++) {
            mipmap = mipmaps[i];
            state.texImage2D(_gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data);
          }
          texture.generateMipmaps = false;
        } else {
          state.texImage2D(_gl.TEXTURE_2D, 0, glFormat, image.width, image.height, 0, glFormat, glType, image.data);
        }
      } else if (texture instanceof THREE.CompressedTexture) {
        for (var i = 0,
            il = mipmaps.length; i < il; i++) {
          mipmap = mipmaps[i];
          if (texture.format !== THREE.RGBAFormat && texture.format !== THREE.RGBFormat) {
            if (state.getCompressedTextureFormats().indexOf(glFormat) > -1) {
              state.compressedTexImage2D(_gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, mipmap.data);
            } else {
              console.warn("THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()");
            }
          } else {
            state.texImage2D(_gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data);
          }
        }
      } else {
        if (mipmaps.length > 0 && isPowerOfTwoImage) {
          for (var i = 0,
              il = mipmaps.length; i < il; i++) {
            mipmap = mipmaps[i];
            state.texImage2D(_gl.TEXTURE_2D, i, glFormat, glFormat, glType, mipmap);
          }
          texture.generateMipmaps = false;
        } else {
          state.texImage2D(_gl.TEXTURE_2D, 0, glFormat, glFormat, glType, image);
        }
      }
      if (texture.generateMipmaps && isPowerOfTwoImage)
        _gl.generateMipmap(_gl.TEXTURE_2D);
      textureProperties.__version = texture.version;
      if (texture.onUpdate)
        texture.onUpdate(texture);
    }
    function setupFrameBufferTexture(framebuffer, renderTarget, attachment, textureTarget) {
      var glFormat = paramThreeToGL(renderTarget.texture.format);
      var glType = paramThreeToGL(renderTarget.texture.type);
      state.texImage2D(textureTarget, 0, glFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null);
      _gl.bindFramebuffer(_gl.FRAMEBUFFER, framebuffer);
      _gl.framebufferTexture2D(_gl.FRAMEBUFFER, attachment, textureTarget, properties.get(renderTarget.texture).__webglTexture, 0);
      _gl.bindFramebuffer(_gl.FRAMEBUFFER, null);
    }
    function setupRenderBufferStorage(renderbuffer, renderTarget) {
      _gl.bindRenderbuffer(_gl.RENDERBUFFER, renderbuffer);
      if (renderTarget.depthBuffer && !renderTarget.stencilBuffer) {
        _gl.renderbufferStorage(_gl.RENDERBUFFER, _gl.DEPTH_COMPONENT16, renderTarget.width, renderTarget.height);
        _gl.framebufferRenderbuffer(_gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer);
      } else if (renderTarget.depthBuffer && renderTarget.stencilBuffer) {
        _gl.renderbufferStorage(_gl.RENDERBUFFER, _gl.DEPTH_STENCIL, renderTarget.width, renderTarget.height);
        _gl.framebufferRenderbuffer(_gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer);
      } else {
        _gl.renderbufferStorage(_gl.RENDERBUFFER, _gl.RGBA4, renderTarget.width, renderTarget.height);
      }
      _gl.bindRenderbuffer(_gl.RENDERBUFFER, null);
    }
    function setupDepthTexture(framebuffer, renderTarget) {
      var isCube = (renderTarget instanceof THREE.WebGLRenderTargetCube);
      if (isCube)
        throw new Error('Depth Texture with cube render targets is not supported!');
      _gl.bindFramebuffer(_gl.FRAMEBUFFER, framebuffer);
      if (!(renderTarget.depthTexture instanceof THREE.DepthTexture)) {
        throw new Error('renderTarget.depthTexture must be an instance of THREE.DepthTexture');
      }
      if (!properties.get(renderTarget.depthTexture).__webglTexture || renderTarget.depthTexture.image.width !== renderTarget.width || renderTarget.depthTexture.image.height !== renderTarget.height) {
        renderTarget.depthTexture.image.width = renderTarget.width;
        renderTarget.depthTexture.image.height = renderTarget.height;
        renderTarget.depthTexture.needsUpdate = true;
      }
      setTexture2D(renderTarget.depthTexture, 0);
      var webglDepthTexture = properties.get(renderTarget.depthTexture).__webglTexture;
      _gl.framebufferTexture2D(_gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0);
    }
    function setupDepthRenderbuffer(renderTarget) {
      var renderTargetProperties = properties.get(renderTarget);
      var isCube = (renderTarget instanceof THREE.WebGLRenderTargetCube);
      if (renderTarget.depthTexture) {
        if (isCube)
          throw new Error('target.depthTexture not supported in Cube render targets');
        setupDepthTexture(renderTargetProperties.__webglFramebuffer, renderTarget);
      } else {
        if (isCube) {
          renderTargetProperties.__webglDepthbuffer = [];
          for (var i = 0; i < 6; i++) {
            _gl.bindFramebuffer(_gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer[i]);
            renderTargetProperties.__webglDepthbuffer[i] = _gl.createRenderbuffer();
            setupRenderBufferStorage(renderTargetProperties.__webglDepthbuffer[i], renderTarget);
          }
        } else {
          _gl.bindFramebuffer(_gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer);
          renderTargetProperties.__webglDepthbuffer = _gl.createRenderbuffer();
          setupRenderBufferStorage(renderTargetProperties.__webglDepthbuffer, renderTarget);
        }
      }
      _gl.bindFramebuffer(_gl.FRAMEBUFFER, null);
    }
    function setupRenderTarget(renderTarget) {
      var renderTargetProperties = properties.get(renderTarget);
      var textureProperties = properties.get(renderTarget.texture);
      renderTarget.addEventListener('dispose', onRenderTargetDispose);
      textureProperties.__webglTexture = _gl.createTexture();
      _infoMemory.textures++;
      var isCube = (renderTarget instanceof THREE.WebGLRenderTargetCube);
      var isTargetPowerOfTwo = isPowerOfTwo(renderTarget);
      if (isCube) {
        renderTargetProperties.__webglFramebuffer = [];
        for (var i = 0; i < 6; i++) {
          renderTargetProperties.__webglFramebuffer[i] = _gl.createFramebuffer();
        }
      } else {
        renderTargetProperties.__webglFramebuffer = _gl.createFramebuffer();
      }
      if (isCube) {
        state.bindTexture(_gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture);
        setTextureParameters(_gl.TEXTURE_CUBE_MAP, renderTarget.texture, isTargetPowerOfTwo);
        for (var i = 0; i < 6; i++) {
          setupFrameBufferTexture(renderTargetProperties.__webglFramebuffer[i], renderTarget, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i);
        }
        if (renderTarget.texture.generateMipmaps && isTargetPowerOfTwo)
          _gl.generateMipmap(_gl.TEXTURE_CUBE_MAP);
        state.bindTexture(_gl.TEXTURE_CUBE_MAP, null);
      } else {
        state.bindTexture(_gl.TEXTURE_2D, textureProperties.__webglTexture);
        setTextureParameters(_gl.TEXTURE_2D, renderTarget.texture, isTargetPowerOfTwo);
        setupFrameBufferTexture(renderTargetProperties.__webglFramebuffer, renderTarget, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D);
        if (renderTarget.texture.generateMipmaps && isTargetPowerOfTwo)
          _gl.generateMipmap(_gl.TEXTURE_2D);
        state.bindTexture(_gl.TEXTURE_2D, null);
      }
      if (renderTarget.depthBuffer) {
        setupDepthRenderbuffer(renderTarget);
      }
    }
    function updateRenderTargetMipmap(renderTarget) {
      var texture = renderTarget.texture;
      if (texture.generateMipmaps && isPowerOfTwo(renderTarget) && texture.minFilter !== THREE.NearestFilter && texture.minFilter !== THREE.LinearFilter) {
        var target = renderTarget instanceof THREE.WebGLRenderTargetCube ? _gl.TEXTURE_CUBE_MAP : _gl.TEXTURE_2D;
        var webglTexture = properties.get(texture).__webglTexture;
        state.bindTexture(target, webglTexture);
        _gl.generateMipmap(target);
        state.bindTexture(target, null);
      }
    }
    this.setTexture2D = setTexture2D;
    this.setTextureCube = setTextureCube;
    this.setTextureCubeDynamic = setTextureCubeDynamic;
    this.setupRenderTarget = setupRenderTarget;
    this.updateRenderTargetMipmap = updateRenderTargetMipmap;
  };
  THREE.WebGLUniforms = (function() {
    var emptyTexture = new THREE.Texture();
    var emptyCubeTexture = new THREE.CubeTexture();
    var UniformContainer = function() {
      this.seq = [];
      this.map = {};
    },
        arrayCacheF32 = [],
        arrayCacheI32 = [],
        uncacheTemporaryArrays = function() {
          arrayCacheF32.length = 0;
          arrayCacheI32.length = 0;
        },
        flatten = function(array, nBlocks, blockSize) {
          var firstElem = array[0];
          if (firstElem <= 0 || firstElem > 0)
            return array;
          var n = nBlocks * blockSize,
              r = arrayCacheF32[n];
          if (r === undefined) {
            r = new Float32Array(n);
            arrayCacheF32[n] = r;
          }
          if (nBlocks !== 0) {
            firstElem.toArray(r, 0);
            for (var i = 1,
                offset = 0; i !== nBlocks; ++i) {
              offset += blockSize;
              array[i].toArray(r, offset);
            }
          }
          return r;
        },
        allocTexUnits = function(renderer, n) {
          var r = arrayCacheI32[n];
          if (r === undefined) {
            r = new Int32Array(n);
            arrayCacheI32[n] = r;
          }
          for (var i = 0; i !== n; ++i)
            r[i] = renderer.allocTextureUnit();
          return r;
        },
        setValue1f = function(gl, v) {
          gl.uniform1f(this.addr, v);
        },
        setValue1i = function(gl, v) {
          gl.uniform1i(this.addr, v);
        },
        setValue2fv = function(gl, v) {
          if (v.x === undefined)
            gl.uniform2fv(this.addr, v);
          else
            gl.uniform2f(this.addr, v.x, v.y);
        },
        setValue3fv = function(gl, v) {
          if (v.x !== undefined)
            gl.uniform3f(this.addr, v.x, v.y, v.z);
          else if (v.r !== undefined)
            gl.uniform3f(this.addr, v.r, v.g, v.b);
          else
            gl.uniform3fv(this.addr, v);
        },
        setValue4fv = function(gl, v) {
          if (v.x === undefined)
            gl.uniform4fv(this.addr, v);
          else
            gl.uniform4f(this.addr, v.x, v.y, v.z, v.w);
        },
        setValue2fm = function(gl, v) {
          gl.uniformMatrix2fv(this.addr, false, v.elements || v);
        },
        setValue3fm = function(gl, v) {
          gl.uniformMatrix3fv(this.addr, false, v.elements || v);
        },
        setValue4fm = function(gl, v) {
          gl.uniformMatrix4fv(this.addr, false, v.elements || v);
        },
        setValueT1 = function(gl, v, renderer) {
          var unit = renderer.allocTextureUnit();
          gl.uniform1i(this.addr, unit);
          renderer.setTexture2D(v || emptyTexture, unit);
        },
        setValueT6 = function(gl, v, renderer) {
          var unit = renderer.allocTextureUnit();
          gl.uniform1i(this.addr, unit);
          renderer.setTextureCube(v || emptyCubeTexture, unit);
        },
        setValue2iv = function(gl, v) {
          gl.uniform2iv(this.addr, v);
        },
        setValue3iv = function(gl, v) {
          gl.uniform3iv(this.addr, v);
        },
        setValue4iv = function(gl, v) {
          gl.uniform4iv(this.addr, v);
        },
        getSingularSetter = function(type) {
          switch (type) {
            case 0x1406:
              return setValue1f;
            case 0x8b50:
              return setValue2fv;
            case 0x8b51:
              return setValue3fv;
            case 0x8b52:
              return setValue4fv;
            case 0x8b5a:
              return setValue2fm;
            case 0x8b5b:
              return setValue3fm;
            case 0x8b5c:
              return setValue4fm;
            case 0x8b5e:
              return setValueT1;
            case 0x8b60:
              return setValueT6;
            case 0x1404:
            case 0x8b56:
              return setValue1i;
            case 0x8b53:
            case 0x8b57:
              return setValue2iv;
            case 0x8b54:
            case 0x8b58:
              return setValue3iv;
            case 0x8b55:
            case 0x8b59:
              return setValue4iv;
          }
        },
        setValue1fv = function(gl, v) {
          gl.uniform1fv(this.addr, v);
        },
        setValue1iv = function(gl, v) {
          gl.uniform1iv(this.addr, v);
        },
        setValueV2a = function(gl, v) {
          gl.uniform2fv(this.addr, flatten(v, this.size, 2));
        },
        setValueV3a = function(gl, v) {
          gl.uniform3fv(this.addr, flatten(v, this.size, 3));
        },
        setValueV4a = function(gl, v) {
          gl.uniform4fv(this.addr, flatten(v, this.size, 4));
        },
        setValueM2a = function(gl, v) {
          gl.uniformMatrix2fv(this.addr, false, flatten(v, this.size, 4));
        },
        setValueM3a = function(gl, v) {
          gl.uniformMatrix3fv(this.addr, false, flatten(v, this.size, 9));
        },
        setValueM4a = function(gl, v) {
          gl.uniformMatrix4fv(this.addr, false, flatten(v, this.size, 16));
        },
        setValueT1a = function(gl, v, renderer) {
          var n = v.length,
              units = allocTexUnits(renderer, n);
          gl.uniform1iv(this.addr, units);
          for (var i = 0; i !== n; ++i) {
            renderer.setTexture2D(v[i] || emptyTexture, units[i]);
          }
        },
        setValueT6a = function(gl, v, renderer) {
          var n = v.length,
              units = allocTexUnits(renderer, n);
          gl.uniform1iv(this.addr, units);
          for (var i = 0; i !== n; ++i) {
            renderer.setTextureCube(v[i] || emptyCubeTexture, units[i]);
          }
        },
        getPureArraySetter = function(type) {
          switch (type) {
            case 0x1406:
              return setValue1fv;
            case 0x8b50:
              return setValueV2a;
            case 0x8b51:
              return setValueV3a;
            case 0x8b52:
              return setValueV4a;
            case 0x8b5a:
              return setValueM2a;
            case 0x8b5b:
              return setValueM3a;
            case 0x8b5c:
              return setValueM4a;
            case 0x8b5e:
              return setValueT1a;
            case 0x8b60:
              return setValueT6a;
            case 0x1404:
            case 0x8b56:
              return setValue1iv;
            case 0x8b53:
            case 0x8b57:
              return setValue2iv;
            case 0x8b54:
            case 0x8b58:
              return setValue3iv;
            case 0x8b55:
            case 0x8b59:
              return setValue4iv;
          }
        },
        SingleUniform = function SingleUniform(id, activeInfo, addr) {
          this.id = id;
          this.addr = addr;
          this.setValue = getSingularSetter(activeInfo.type);
        },
        PureArrayUniform = function(id, activeInfo, addr) {
          this.id = id;
          this.addr = addr;
          this.size = activeInfo.size;
          this.setValue = getPureArraySetter(activeInfo.type);
        },
        StructuredUniform = function(id) {
          this.id = id;
          UniformContainer.call(this);
        };
    StructuredUniform.prototype.setValue = function(gl, value) {
      var seq = this.seq;
      for (var i = 0,
          n = seq.length; i !== n; ++i) {
        var u = seq[i];
        u.setValue(gl, value[u.id]);
      }
    };
    var RePathPart = /([\w\d_]+)(\])?(\[|\.)?/g,
        addUniform = function(container, uniformObject) {
          container.seq.push(uniformObject);
          container.map[uniformObject.id] = uniformObject;
        },
        parseUniform = function(activeInfo, addr, container) {
          var path = activeInfo.name,
              pathLength = path.length;
          RePathPart.lastIndex = 0;
          for (; ; ) {
            var match = RePathPart.exec(path),
                matchEnd = RePathPart.lastIndex,
                id = match[1],
                idIsIndex = match[2] === ']',
                subscript = match[3];
            if (idIsIndex)
              id = id | 0;
            if (subscript === undefined || subscript === '[' && matchEnd + 2 === pathLength) {
              addUniform(container, subscript === undefined ? new SingleUniform(id, activeInfo, addr) : new PureArrayUniform(id, activeInfo, addr));
              break;
            } else {
              var map = container.map,
                  next = map[id];
              if (next === undefined) {
                next = new StructuredUniform(id);
                addUniform(container, next);
              }
              container = next;
            }
          }
        },
        WebGLUniforms = function WebGLUniforms(gl, program, renderer) {
          UniformContainer.call(this);
          this.renderer = renderer;
          var n = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
          for (var i = 0; i !== n; ++i) {
            var info = gl.getActiveUniform(program, i),
                path = info.name,
                addr = gl.getUniformLocation(program, path);
            parseUniform(info, addr, this);
          }
        };
    WebGLUniforms.prototype.setValue = function(gl, name, value) {
      var u = this.map[name];
      if (u !== undefined)
        u.setValue(gl, value, this.renderer);
    };
    WebGLUniforms.prototype.set = function(gl, object, name) {
      var u = this.map[name];
      if (u !== undefined)
        u.setValue(gl, object[name], this.renderer);
    };
    WebGLUniforms.prototype.setOptional = function(gl, object, name) {
      var v = object[name];
      if (v !== undefined)
        this.setValue(gl, name, v);
    };
    WebGLUniforms.upload = function(gl, seq, values, renderer) {
      for (var i = 0,
          n = seq.length; i !== n; ++i) {
        var u = seq[i],
            v = values[u.id];
        if (v.needsUpdate !== false) {
          u.setValue(gl, v.value, renderer);
        }
      }
    };
    WebGLUniforms.seqWithValue = function(seq, values) {
      var r = [];
      for (var i = 0,
          n = seq.length; i !== n; ++i) {
        var u = seq[i];
        if (u.id in values)
          r.push(u);
      }
      return r;
    };
    WebGLUniforms.splitDynamic = function(seq, values) {
      var r = null,
          n = seq.length,
          w = 0;
      for (var i = 0; i !== n; ++i) {
        var u = seq[i],
            v = values[u.id];
        if (v && v.dynamic === true) {
          if (r === null)
            r = [];
          r.push(u);
        } else {
          if (w < i)
            seq[w] = u;
          ++w;
        }
      }
      if (w < n)
        seq.length = w;
      return r;
    };
    WebGLUniforms.evalDynamic = function(seq, values, object, camera) {
      for (var i = 0,
          n = seq.length; i !== n; ++i) {
        var v = values[seq[i].id],
            f = v.onUpdateCallback;
        if (f !== undefined)
          f.call(v, object, camera);
      }
    };
    return WebGLUniforms;
  })();
  THREE.LensFlarePlugin = function(renderer, flares) {
    var gl = renderer.context;
    var state = renderer.state;
    var vertexBuffer,
        elementBuffer;
    var shader,
        program,
        attributes,
        uniforms;
    var tempTexture,
        occlusionTexture;
    function init() {
      var vertices = new Float32Array([-1, -1, 0, 0, 1, -1, 1, 0, 1, 1, 1, 1, -1, 1, 0, 1]);
      var faces = new Uint16Array([0, 1, 2, 0, 2, 3]);
      vertexBuffer = gl.createBuffer();
      elementBuffer = gl.createBuffer();
      gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
      gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
      gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementBuffer);
      gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, faces, gl.STATIC_DRAW);
      tempTexture = gl.createTexture();
      occlusionTexture = gl.createTexture();
      state.bindTexture(gl.TEXTURE_2D, tempTexture);
      gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, 16, 16, 0, gl.RGB, gl.UNSIGNED_BYTE, null);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
      state.bindTexture(gl.TEXTURE_2D, occlusionTexture);
      gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 16, 16, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
      gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
      shader = {
        vertexShader: ["uniform lowp int renderType;", "uniform vec3 screenPosition;", "uniform vec2 scale;", "uniform float rotation;", "uniform sampler2D occlusionMap;", "attribute vec2 position;", "attribute vec2 uv;", "varying vec2 vUV;", "varying float vVisibility;", "void main() {", "vUV = uv;", "vec2 pos = position;", "if ( renderType == 2 ) {", "vec4 visibility = texture2D( occlusionMap, vec2( 0.1, 0.1 ) );", "visibility += texture2D( occlusionMap, vec2( 0.5, 0.1 ) );", "visibility += texture2D( occlusionMap, vec2( 0.9, 0.1 ) );", "visibility += texture2D( occlusionMap, vec2( 0.9, 0.5 ) );", "visibility += texture2D( occlusionMap, vec2( 0.9, 0.9 ) );", "visibility += texture2D( occlusionMap, vec2( 0.5, 0.9 ) );", "visibility += texture2D( occlusionMap, vec2( 0.1, 0.9 ) );", "visibility += texture2D( occlusionMap, vec2( 0.1, 0.5 ) );", "visibility += texture2D( occlusionMap, vec2( 0.5, 0.5 ) );", "vVisibility =        visibility.r / 9.0;", "vVisibility *= 1.0 - visibility.g / 9.0;", "vVisibility *=       visibility.b / 9.0;", "vVisibility *= 1.0 - visibility.a / 9.0;", "pos.x = cos( rotation ) * position.x - sin( rotation ) * position.y;", "pos.y = sin( rotation ) * position.x + cos( rotation ) * position.y;", "}", "gl_Position = vec4( ( pos * scale + screenPosition.xy ).xy, screenPosition.z, 1.0 );", "}"].join("\n"),
        fragmentShader: ["uniform lowp int renderType;", "uniform sampler2D map;", "uniform float opacity;", "uniform vec3 color;", "varying vec2 vUV;", "varying float vVisibility;", "void main() {", "if ( renderType == 0 ) {", "gl_FragColor = vec4( 1.0, 0.0, 1.0, 0.0 );", "} else if ( renderType == 1 ) {", "gl_FragColor = texture2D( map, vUV );", "} else {", "vec4 texture = texture2D( map, vUV );", "texture.a *= opacity * vVisibility;", "gl_FragColor = texture;", "gl_FragColor.rgb *= color;", "}", "}"].join("\n")
      };
      program = createProgram(shader);
      attributes = {
        vertex: gl.getAttribLocation(program, "position"),
        uv: gl.getAttribLocation(program, "uv")
      };
      uniforms = {
        renderType: gl.getUniformLocation(program, "renderType"),
        map: gl.getUniformLocation(program, "map"),
        occlusionMap: gl.getUniformLocation(program, "occlusionMap"),
        opacity: gl.getUniformLocation(program, "opacity"),
        color: gl.getUniformLocation(program, "color"),
        scale: gl.getUniformLocation(program, "scale"),
        rotation: gl.getUniformLocation(program, "rotation"),
        screenPosition: gl.getUniformLocation(program, "screenPosition")
      };
    }
    this.render = function(scene, camera, viewport) {
      if (flares.length === 0)
        return;
      var tempPosition = new THREE.Vector3();
      var invAspect = viewport.w / viewport.z,
          halfViewportWidth = viewport.z * 0.5,
          halfViewportHeight = viewport.w * 0.5;
      var size = 16 / viewport.w,
          scale = new THREE.Vector2(size * invAspect, size);
      var screenPosition = new THREE.Vector3(1, 1, 0),
          screenPositionPixels = new THREE.Vector2(1, 1);
      var validArea = new THREE.Box2();
      validArea.min.set(0, 0);
      validArea.max.set(viewport.z - 16, viewport.w - 16);
      if (program === undefined) {
        init();
      }
      gl.useProgram(program);
      state.initAttributes();
      state.enableAttribute(attributes.vertex);
      state.enableAttribute(attributes.uv);
      state.disableUnusedAttributes();
      gl.uniform1i(uniforms.occlusionMap, 0);
      gl.uniform1i(uniforms.map, 1);
      gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
      gl.vertexAttribPointer(attributes.vertex, 2, gl.FLOAT, false, 2 * 8, 0);
      gl.vertexAttribPointer(attributes.uv, 2, gl.FLOAT, false, 2 * 8, 8);
      gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementBuffer);
      state.disable(gl.CULL_FACE);
      state.setDepthWrite(false);
      for (var i = 0,
          l = flares.length; i < l; i++) {
        size = 16 / viewport.w;
        scale.set(size * invAspect, size);
        var flare = flares[i];
        tempPosition.set(flare.matrixWorld.elements[12], flare.matrixWorld.elements[13], flare.matrixWorld.elements[14]);
        tempPosition.applyMatrix4(camera.matrixWorldInverse);
        tempPosition.applyProjection(camera.projectionMatrix);
        screenPosition.copy(tempPosition);
        screenPositionPixels.x = viewport.x + (screenPosition.x * halfViewportWidth) + halfViewportWidth - 8;
        screenPositionPixels.y = viewport.y + (screenPosition.y * halfViewportHeight) + halfViewportHeight - 8;
        if (validArea.containsPoint(screenPositionPixels) === true) {
          state.activeTexture(gl.TEXTURE0);
          state.bindTexture(gl.TEXTURE_2D, null);
          state.activeTexture(gl.TEXTURE1);
          state.bindTexture(gl.TEXTURE_2D, tempTexture);
          gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGB, screenPositionPixels.x, screenPositionPixels.y, 16, 16, 0);
          gl.uniform1i(uniforms.renderType, 0);
          gl.uniform2f(uniforms.scale, scale.x, scale.y);
          gl.uniform3f(uniforms.screenPosition, screenPosition.x, screenPosition.y, screenPosition.z);
          state.disable(gl.BLEND);
          state.enable(gl.DEPTH_TEST);
          gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
          state.activeTexture(gl.TEXTURE0);
          state.bindTexture(gl.TEXTURE_2D, occlusionTexture);
          gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, screenPositionPixels.x, screenPositionPixels.y, 16, 16, 0);
          gl.uniform1i(uniforms.renderType, 1);
          state.disable(gl.DEPTH_TEST);
          state.activeTexture(gl.TEXTURE1);
          state.bindTexture(gl.TEXTURE_2D, tempTexture);
          gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
          flare.positionScreen.copy(screenPosition);
          if (flare.customUpdateCallback) {
            flare.customUpdateCallback(flare);
          } else {
            flare.updateLensFlares();
          }
          gl.uniform1i(uniforms.renderType, 2);
          state.enable(gl.BLEND);
          for (var j = 0,
              jl = flare.lensFlares.length; j < jl; j++) {
            var sprite = flare.lensFlares[j];
            if (sprite.opacity > 0.001 && sprite.scale > 0.001) {
              screenPosition.x = sprite.x;
              screenPosition.y = sprite.y;
              screenPosition.z = sprite.z;
              size = sprite.size * sprite.scale / viewport.w;
              scale.x = size * invAspect;
              scale.y = size;
              gl.uniform3f(uniforms.screenPosition, screenPosition.x, screenPosition.y, screenPosition.z);
              gl.uniform2f(uniforms.scale, scale.x, scale.y);
              gl.uniform1f(uniforms.rotation, sprite.rotation);
              gl.uniform1f(uniforms.opacity, sprite.opacity);
              gl.uniform3f(uniforms.color, sprite.color.r, sprite.color.g, sprite.color.b);
              state.setBlending(sprite.blending, sprite.blendEquation, sprite.blendSrc, sprite.blendDst);
              renderer.setTexture2D(sprite.texture, 1);
              gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
            }
          }
        }
      }
      state.enable(gl.CULL_FACE);
      state.enable(gl.DEPTH_TEST);
      state.setDepthWrite(true);
      renderer.resetGLState();
    };
    function createProgram(shader) {
      var program = gl.createProgram();
      var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
      var vertexShader = gl.createShader(gl.VERTEX_SHADER);
      var prefix = "precision " + renderer.getPrecision() + " float;\n";
      gl.shaderSource(fragmentShader, prefix + shader.fragmentShader);
      gl.shaderSource(vertexShader, prefix + shader.vertexShader);
      gl.compileShader(fragmentShader);
      gl.compileShader(vertexShader);
      gl.attachShader(program, fragmentShader);
      gl.attachShader(program, vertexShader);
      gl.linkProgram(program);
      return program;
    }
  };
  THREE.SpritePlugin = function(renderer, sprites) {
    var gl = renderer.context;
    var state = renderer.state;
    var vertexBuffer,
        elementBuffer;
    var program,
        attributes,
        uniforms;
    var texture;
    var spritePosition = new THREE.Vector3();
    var spriteRotation = new THREE.Quaternion();
    var spriteScale = new THREE.Vector3();
    function init() {
      var vertices = new Float32Array([-0.5, -0.5, 0, 0, 0.5, -0.5, 1, 0, 0.5, 0.5, 1, 1, -0.5, 0.5, 0, 1]);
      var faces = new Uint16Array([0, 1, 2, 0, 2, 3]);
      vertexBuffer = gl.createBuffer();
      elementBuffer = gl.createBuffer();
      gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
      gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
      gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementBuffer);
      gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, faces, gl.STATIC_DRAW);
      program = createProgram();
      attributes = {
        position: gl.getAttribLocation(program, 'position'),
        uv: gl.getAttribLocation(program, 'uv')
      };
      uniforms = {
        uvOffset: gl.getUniformLocation(program, 'uvOffset'),
        uvScale: gl.getUniformLocation(program, 'uvScale'),
        rotation: gl.getUniformLocation(program, 'rotation'),
        scale: gl.getUniformLocation(program, 'scale'),
        color: gl.getUniformLocation(program, 'color'),
        map: gl.getUniformLocation(program, 'map'),
        opacity: gl.getUniformLocation(program, 'opacity'),
        modelViewMatrix: gl.getUniformLocation(program, 'modelViewMatrix'),
        projectionMatrix: gl.getUniformLocation(program, 'projectionMatrix'),
        fogType: gl.getUniformLocation(program, 'fogType'),
        fogDensity: gl.getUniformLocation(program, 'fogDensity'),
        fogNear: gl.getUniformLocation(program, 'fogNear'),
        fogFar: gl.getUniformLocation(program, 'fogFar'),
        fogColor: gl.getUniformLocation(program, 'fogColor'),
        alphaTest: gl.getUniformLocation(program, 'alphaTest')
      };
      var canvas = document.createElementNS('http://www.w3.org/1999/xhtml', 'canvas');
      canvas.width = 8;
      canvas.height = 8;
      var context = canvas.getContext('2d');
      context.fillStyle = 'white';
      context.fillRect(0, 0, 8, 8);
      texture = new THREE.Texture(canvas);
      texture.needsUpdate = true;
    }
    this.render = function(scene, camera) {
      if (sprites.length === 0)
        return;
      if (program === undefined) {
        init();
      }
      gl.useProgram(program);
      state.initAttributes();
      state.enableAttribute(attributes.position);
      state.enableAttribute(attributes.uv);
      state.disableUnusedAttributes();
      state.disable(gl.CULL_FACE);
      state.enable(gl.BLEND);
      gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
      gl.vertexAttribPointer(attributes.position, 2, gl.FLOAT, false, 2 * 8, 0);
      gl.vertexAttribPointer(attributes.uv, 2, gl.FLOAT, false, 2 * 8, 8);
      gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elementBuffer);
      gl.uniformMatrix4fv(uniforms.projectionMatrix, false, camera.projectionMatrix.elements);
      state.activeTexture(gl.TEXTURE0);
      gl.uniform1i(uniforms.map, 0);
      var oldFogType = 0;
      var sceneFogType = 0;
      var fog = scene.fog;
      if (fog) {
        gl.uniform3f(uniforms.fogColor, fog.color.r, fog.color.g, fog.color.b);
        if (fog instanceof THREE.Fog) {
          gl.uniform1f(uniforms.fogNear, fog.near);
          gl.uniform1f(uniforms.fogFar, fog.far);
          gl.uniform1i(uniforms.fogType, 1);
          oldFogType = 1;
          sceneFogType = 1;
        } else if (fog instanceof THREE.FogExp2) {
          gl.uniform1f(uniforms.fogDensity, fog.density);
          gl.uniform1i(uniforms.fogType, 2);
          oldFogType = 2;
          sceneFogType = 2;
        }
      } else {
        gl.uniform1i(uniforms.fogType, 0);
        oldFogType = 0;
        sceneFogType = 0;
      }
      for (var i = 0,
          l = sprites.length; i < l; i++) {
        var sprite = sprites[i];
        sprite.modelViewMatrix.multiplyMatrices(camera.matrixWorldInverse, sprite.matrixWorld);
        sprite.z = -sprite.modelViewMatrix.elements[14];
      }
      sprites.sort(painterSortStable);
      var scale = [];
      for (var i = 0,
          l = sprites.length; i < l; i++) {
        var sprite = sprites[i];
        var material = sprite.material;
        gl.uniform1f(uniforms.alphaTest, material.alphaTest);
        gl.uniformMatrix4fv(uniforms.modelViewMatrix, false, sprite.modelViewMatrix.elements);
        sprite.matrixWorld.decompose(spritePosition, spriteRotation, spriteScale);
        scale[0] = spriteScale.x;
        scale[1] = spriteScale.y;
        var fogType = 0;
        if (scene.fog && material.fog) {
          fogType = sceneFogType;
        }
        if (oldFogType !== fogType) {
          gl.uniform1i(uniforms.fogType, fogType);
          oldFogType = fogType;
        }
        if (material.map !== null) {
          gl.uniform2f(uniforms.uvOffset, material.map.offset.x, material.map.offset.y);
          gl.uniform2f(uniforms.uvScale, material.map.repeat.x, material.map.repeat.y);
        } else {
          gl.uniform2f(uniforms.uvOffset, 0, 0);
          gl.uniform2f(uniforms.uvScale, 1, 1);
        }
        gl.uniform1f(uniforms.opacity, material.opacity);
        gl.uniform3f(uniforms.color, material.color.r, material.color.g, material.color.b);
        gl.uniform1f(uniforms.rotation, material.rotation);
        gl.uniform2fv(uniforms.scale, scale);
        state.setBlending(material.blending, material.blendEquation, material.blendSrc, material.blendDst);
        state.setDepthTest(material.depthTest);
        state.setDepthWrite(material.depthWrite);
        if (material.map) {
          renderer.setTexture2D(material.map, 0);
        } else {
          renderer.setTexture2D(texture, 0);
        }
        gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
      }
      state.enable(gl.CULL_FACE);
      renderer.resetGLState();
    };
    function createProgram() {
      var program = gl.createProgram();
      var vertexShader = gl.createShader(gl.VERTEX_SHADER);
      var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
      gl.shaderSource(vertexShader, ['precision ' + renderer.getPrecision() + ' float;', 'uniform mat4 modelViewMatrix;', 'uniform mat4 projectionMatrix;', 'uniform float rotation;', 'uniform vec2 scale;', 'uniform vec2 uvOffset;', 'uniform vec2 uvScale;', 'attribute vec2 position;', 'attribute vec2 uv;', 'varying vec2 vUV;', 'void main() {', 'vUV = uvOffset + uv * uvScale;', 'vec2 alignedPosition = position * scale;', 'vec2 rotatedPosition;', 'rotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;', 'rotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;', 'vec4 finalPosition;', 'finalPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );', 'finalPosition.xy += rotatedPosition;', 'finalPosition = projectionMatrix * finalPosition;', 'gl_Position = finalPosition;', '}'].join('\n'));
      gl.shaderSource(fragmentShader, ['precision ' + renderer.getPrecision() + ' float;', 'uniform vec3 color;', 'uniform sampler2D map;', 'uniform float opacity;', 'uniform int fogType;', 'uniform vec3 fogColor;', 'uniform float fogDensity;', 'uniform float fogNear;', 'uniform float fogFar;', 'uniform float alphaTest;', 'varying vec2 vUV;', 'void main() {', 'vec4 texture = texture2D( map, vUV );', 'if ( texture.a < alphaTest ) discard;', 'gl_FragColor = vec4( color * texture.xyz, texture.a * opacity );', 'if ( fogType > 0 ) {', 'float depth = gl_FragCoord.z / gl_FragCoord.w;', 'float fogFactor = 0.0;', 'if ( fogType == 1 ) {', 'fogFactor = smoothstep( fogNear, fogFar, depth );', '} else {', 'const float LOG2 = 1.442695;', 'fogFactor = exp2( - fogDensity * fogDensity * depth * depth * LOG2 );', 'fogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );', '}', 'gl_FragColor = mix( gl_FragColor, vec4( fogColor, gl_FragColor.w ), fogFactor );', '}', '}'].join('\n'));
      gl.compileShader(vertexShader);
      gl.compileShader(fragmentShader);
      gl.attachShader(program, vertexShader);
      gl.attachShader(program, fragmentShader);
      gl.linkProgram(program);
      return program;
    }
    function painterSortStable(a, b) {
      if (a.renderOrder !== b.renderOrder) {
        return a.renderOrder - b.renderOrder;
      } else if (a.z !== b.z) {
        return b.z - a.z;
      } else {
        return b.id - a.id;
      }
    }
  };
  Object.assign(THREE, {
    Face4: function(a, b, c, d, normal, color, materialIndex) {
      console.warn('THREE.Face4 has been removed. A THREE.Face3 will be created instead.');
      return new THREE.Face3(a, b, c, normal, color, materialIndex);
    },
    LineStrip: 0,
    LinePieces: 1,
    MeshFaceMaterial: THREE.MultiMaterial,
    PointCloud: function(geometry, material) {
      console.warn('THREE.PointCloud has been renamed to THREE.Points.');
      return new THREE.Points(geometry, material);
    },
    Particle: THREE.Sprite,
    ParticleSystem: function(geometry, material) {
      console.warn('THREE.ParticleSystem has been renamed to THREE.Points.');
      return new THREE.Points(geometry, material);
    },
    PointCloudMaterial: function(parameters) {
      console.warn('THREE.PointCloudMaterial has been renamed to THREE.PointsMaterial.');
      return new THREE.PointsMaterial(parameters);
    },
    ParticleBasicMaterial: function(parameters) {
      console.warn('THREE.ParticleBasicMaterial has been renamed to THREE.PointsMaterial.');
      return new THREE.PointsMaterial(parameters);
    },
    ParticleSystemMaterial: function(parameters) {
      console.warn('THREE.ParticleSystemMaterial has been renamed to THREE.PointsMaterial.');
      return new THREE.PointsMaterial(parameters);
    },
    Vertex: function(x, y, z) {
      console.warn('THREE.Vertex has been removed. Use THREE.Vector3 instead.');
      return new THREE.Vector3(x, y, z);
    }
  });
  Object.assign(THREE.Box2.prototype, {
    empty: function() {
      console.warn('THREE.Box2: .empty() has been renamed to .isEmpty().');
      return this.isEmpty();
    },
    isIntersectionBox: function(box) {
      console.warn('THREE.Box2: .isIntersectionBox() has been renamed to .intersectsBox().');
      return this.intersectsBox(box);
    }
  });
  Object.assign(THREE.Box3.prototype, {
    empty: function() {
      console.warn('THREE.Box3: .empty() has been renamed to .isEmpty().');
      return this.isEmpty();
    },
    isIntersectionBox: function(box) {
      console.warn('THREE.Box3: .isIntersectionBox() has been renamed to .intersectsBox().');
      return this.intersectsBox(box);
    },
    isIntersectionSphere: function(sphere) {
      console.warn('THREE.Box3: .isIntersectionSphere() has been renamed to .intersectsSphere().');
      return this.intersectsSphere(sphere);
    }
  });
  Object.assign(THREE.Matrix3.prototype, {
    multiplyVector3: function(vector) {
      console.warn('THREE.Matrix3: .multiplyVector3() has been removed. Use vector.applyMatrix3( matrix ) instead.');
      return vector.applyMatrix3(this);
    },
    multiplyVector3Array: function(a) {
      console.warn('THREE.Matrix3: .multiplyVector3Array() has been renamed. Use matrix.applyToVector3Array( array ) instead.');
      return this.applyToVector3Array(a);
    }
  });
  Object.assign(THREE.Matrix4.prototype, {
    extractPosition: function(m) {
      console.warn('THREE.Matrix4: .extractPosition() has been renamed to .copyPosition().');
      return this.copyPosition(m);
    },
    setRotationFromQuaternion: function(q) {
      console.warn('THREE.Matrix4: .setRotationFromQuaternion() has been renamed to .makeRotationFromQuaternion().');
      return this.makeRotationFromQuaternion(q);
    },
    multiplyVector3: function(vector) {
      console.warn('THREE.Matrix4: .multiplyVector3() has been removed. Use vector.applyMatrix4( matrix ) or vector.applyProjection( matrix ) instead.');
      return vector.applyProjection(this);
    },
    multiplyVector4: function(vector) {
      console.warn('THREE.Matrix4: .multiplyVector4() has been removed. Use vector.applyMatrix4( matrix ) instead.');
      return vector.applyMatrix4(this);
    },
    multiplyVector3Array: function(a) {
      console.warn('THREE.Matrix4: .multiplyVector3Array() has been renamed. Use matrix.applyToVector3Array( array ) instead.');
      return this.applyToVector3Array(a);
    },
    rotateAxis: function(v) {
      console.warn('THREE.Matrix4: .rotateAxis() has been removed. Use Vector3.transformDirection( matrix ) instead.');
      v.transformDirection(this);
    },
    crossVector: function(vector) {
      console.warn('THREE.Matrix4: .crossVector() has been removed. Use vector.applyMatrix4( matrix ) instead.');
      return vector.applyMatrix4(this);
    },
    translate: function(v) {
      console.error('THREE.Matrix4: .translate() has been removed.');
    },
    rotateX: function(angle) {
      console.error('THREE.Matrix4: .rotateX() has been removed.');
    },
    rotateY: function(angle) {
      console.error('THREE.Matrix4: .rotateY() has been removed.');
    },
    rotateZ: function(angle) {
      console.error('THREE.Matrix4: .rotateZ() has been removed.');
    },
    rotateByAxis: function(axis, angle) {
      console.error('THREE.Matrix4: .rotateByAxis() has been removed.');
    }
  });
  Object.assign(THREE.Plane.prototype, {isIntersectionLine: function(line) {
      console.warn('THREE.Plane: .isIntersectionLine() has been renamed to .intersectsLine().');
      return this.intersectsLine(line);
    }});
  Object.assign(THREE.Quaternion.prototype, {multiplyVector3: function(vector) {
      console.warn('THREE.Quaternion: .multiplyVector3() has been removed. Use is now vector.applyQuaternion( quaternion ) instead.');
      return vector.applyQuaternion(this);
    }});
  Object.assign(THREE.Ray.prototype, {
    isIntersectionBox: function(box) {
      console.warn('THREE.Ray: .isIntersectionBox() has been renamed to .intersectsBox().');
      return this.intersectsBox(box);
    },
    isIntersectionPlane: function(plane) {
      console.warn('THREE.Ray: .isIntersectionPlane() has been renamed to .intersectsPlane().');
      return this.intersectsPlane(plane);
    },
    isIntersectionSphere: function(sphere) {
      console.warn('THREE.Ray: .isIntersectionSphere() has been renamed to .intersectsSphere().');
      return this.intersectsSphere(sphere);
    }
  });
  Object.assign(THREE.Vector3.prototype, {
    setEulerFromRotationMatrix: function() {
      console.error('THREE.Vector3: .setEulerFromRotationMatrix() has been removed. Use Euler.setFromRotationMatrix() instead.');
    },
    setEulerFromQuaternion: function() {
      console.error('THREE.Vector3: .setEulerFromQuaternion() has been removed. Use Euler.setFromQuaternion() instead.');
    },
    getPositionFromMatrix: function(m) {
      console.warn('THREE.Vector3: .getPositionFromMatrix() has been renamed to .setFromMatrixPosition().');
      return this.setFromMatrixPosition(m);
    },
    getScaleFromMatrix: function(m) {
      console.warn('THREE.Vector3: .getScaleFromMatrix() has been renamed to .setFromMatrixScale().');
      return this.setFromMatrixScale(m);
    },
    getColumnFromMatrix: function(index, matrix) {
      console.warn('THREE.Vector3: .getColumnFromMatrix() has been renamed to .setFromMatrixColumn().');
      return this.setFromMatrixColumn(matrix, index);
    }
  });
  Object.assign(THREE.Object3D.prototype, {
    getChildByName: function(name) {
      console.warn('THREE.Object3D: .getChildByName() has been renamed to .getObjectByName().');
      return this.getObjectByName(name);
    },
    renderDepth: function(value) {
      console.warn('THREE.Object3D: .renderDepth has been removed. Use .renderOrder, instead.');
    },
    translate: function(distance, axis) {
      console.warn('THREE.Object3D: .translate() has been removed. Use .translateOnAxis( axis, distance ) instead.');
      return this.translateOnAxis(axis, distance);
    }
  });
  Object.defineProperties(THREE.Object3D.prototype, {
    eulerOrder: {
      get: function() {
        console.warn('THREE.Object3D: .eulerOrder is now .rotation.order.');
        return this.rotation.order;
      },
      set: function(value) {
        console.warn('THREE.Object3D: .eulerOrder is now .rotation.order.');
        this.rotation.order = value;
      }
    },
    useQuaternion: {
      get: function() {
        console.warn('THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.');
      },
      set: function(value) {
        console.warn('THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.');
      }
    }
  });
  Object.defineProperties(THREE.LOD.prototype, {objects: {get: function() {
        console.warn('THREE.LOD: .objects has been renamed to .levels.');
        return this.levels;
      }}});
  THREE.PerspectiveCamera.prototype.setLens = function(focalLength, filmGauge) {
    console.warn("THREE.PerspectiveCamera.setLens is deprecated. " + "Use .setFocalLength and .filmGauge for a photographic setup.");
    if (filmGauge !== undefined)
      this.filmGauge = filmGauge;
    this.setFocalLength(focalLength);
  };
  Object.defineProperties(THREE.Light.prototype, {
    onlyShadow: {set: function(value) {
        console.warn('THREE.Light: .onlyShadow has been removed.');
      }},
    shadowCameraFov: {set: function(value) {
        console.warn('THREE.Light: .shadowCameraFov is now .shadow.camera.fov.');
        this.shadow.camera.fov = value;
      }},
    shadowCameraLeft: {set: function(value) {
        console.warn('THREE.Light: .shadowCameraLeft is now .shadow.camera.left.');
        this.shadow.camera.left = value;
      }},
    shadowCameraRight: {set: function(value) {
        console.warn('THREE.Light: .shadowCameraRight is now .shadow.camera.right.');
        this.shadow.camera.right = value;
      }},
    shadowCameraTop: {set: function(value) {
        console.warn('THREE.Light: .shadowCameraTop is now .shadow.camera.top.');
        this.shadow.camera.top = value;
      }},
    shadowCameraBottom: {set: function(value) {
        console.warn('THREE.Light: .shadowCameraBottom is now .shadow.camera.bottom.');
        this.shadow.camera.bottom = value;
      }},
    shadowCameraNear: {set: function(value) {
        console.warn('THREE.Light: .shadowCameraNear is now .shadow.camera.near.');
        this.shadow.camera.near = value;
      }},
    shadowCameraFar: {set: function(value) {
        console.warn('THREE.Light: .shadowCameraFar is now .shadow.camera.far.');
        this.shadow.camera.far = value;
      }},
    shadowCameraVisible: {set: function(value) {
        console.warn('THREE.Light: .shadowCameraVisible has been removed. Use new THREE.CameraHelper( light.shadow.camera ) instead.');
      }},
    shadowBias: {set: function(value) {
        console.warn('THREE.Light: .shadowBias is now .shadow.bias.');
        this.shadow.bias = value;
      }},
    shadowDarkness: {set: function(value) {
        console.warn('THREE.Light: .shadowDarkness has been removed.');
      }},
    shadowMapWidth: {set: function(value) {
        console.warn('THREE.Light: .shadowMapWidth is now .shadow.mapSize.width.');
        this.shadow.mapSize.width = value;
      }},
    shadowMapHeight: {set: function(value) {
        console.warn('THREE.Light: .shadowMapHeight is now .shadow.mapSize.height.');
        this.shadow.mapSize.height = value;
      }}
  });
  Object.defineProperties(THREE.BufferAttribute.prototype, {length: {get: function() {
        console.warn('THREE.BufferAttribute: .length has been deprecated. Please use .count.');
        return this.array.length;
      }}});
  Object.assign(THREE.BufferGeometry.prototype, {
    addIndex: function(index) {
      console.warn('THREE.BufferGeometry: .addIndex() has been renamed to .setIndex().');
      this.setIndex(index);
    },
    addDrawCall: function(start, count, indexOffset) {
      if (indexOffset !== undefined) {
        console.warn('THREE.BufferGeometry: .addDrawCall() no longer supports indexOffset.');
      }
      console.warn('THREE.BufferGeometry: .addDrawCall() is now .addGroup().');
      this.addGroup(start, count);
    },
    clearDrawCalls: function() {
      console.warn('THREE.BufferGeometry: .clearDrawCalls() is now .clearGroups().');
      this.clearGroups();
    },
    computeTangents: function() {
      console.warn('THREE.BufferGeometry: .computeTangents() has been removed.');
    },
    computeOffsets: function() {
      console.warn('THREE.BufferGeometry: .computeOffsets() has been removed.');
    }
  });
  Object.defineProperties(THREE.BufferGeometry.prototype, {
    drawcalls: {get: function() {
        console.error('THREE.BufferGeometry: .drawcalls has been renamed to .groups.');
        return this.groups;
      }},
    offsets: {get: function() {
        console.warn('THREE.BufferGeometry: .offsets has been renamed to .groups.');
        return this.groups;
      }}
  });
  Object.defineProperties(THREE.Material.prototype, {
    wrapAround: {
      get: function() {
        console.warn('THREE.' + this.type + ': .wrapAround has been removed.');
      },
      set: function(value) {
        console.warn('THREE.' + this.type + ': .wrapAround has been removed.');
      }
    },
    wrapRGB: {get: function() {
        console.warn('THREE.' + this.type + ': .wrapRGB has been removed.');
        return new THREE.Color();
      }}
  });
  Object.defineProperties(THREE.MeshPhongMaterial.prototype, {metal: {
      get: function() {
        console.warn('THREE.MeshPhongMaterial: .metal has been removed. Use THREE.MeshStandardMaterial instead.');
        return false;
      },
      set: function(value) {
        console.warn('THREE.MeshPhongMaterial: .metal has been removed. Use THREE.MeshStandardMaterial instead');
      }
    }});
  Object.defineProperties(THREE.ShaderMaterial.prototype, {derivatives: {
      get: function() {
        console.warn('THREE.ShaderMaterial: .derivatives has been moved to .extensions.derivatives.');
        return this.extensions.derivatives;
      },
      set: function(value) {
        console.warn('THREE. ShaderMaterial: .derivatives has been moved to .extensions.derivatives.');
        this.extensions.derivatives = value;
      }
    }});
  THREE.EventDispatcher.prototype = Object.assign(Object.create({
    constructor: THREE.EventDispatcher,
    apply: function(target) {
      console.warn("THREE.EventDispatcher: .apply is deprecated, " + "just inherit or Object.assign the prototype to mix-in.");
      Object.assign(target, this);
    }
  }), THREE.EventDispatcher.prototype);
  Object.assign(THREE.WebGLRenderer.prototype, {
    supportsFloatTextures: function() {
      console.warn('THREE.WebGLRenderer: .supportsFloatTextures() is now .extensions.get( \'OES_texture_float\' ).');
      return this.extensions.get('OES_texture_float');
    },
    supportsHalfFloatTextures: function() {
      console.warn('THREE.WebGLRenderer: .supportsHalfFloatTextures() is now .extensions.get( \'OES_texture_half_float\' ).');
      return this.extensions.get('OES_texture_half_float');
    },
    supportsStandardDerivatives: function() {
      console.warn('THREE.WebGLRenderer: .supportsStandardDerivatives() is now .extensions.get( \'OES_standard_derivatives\' ).');
      return this.extensions.get('OES_standard_derivatives');
    },
    supportsCompressedTextureS3TC: function() {
      console.warn('THREE.WebGLRenderer: .supportsCompressedTextureS3TC() is now .extensions.get( \'WEBGL_compressed_texture_s3tc\' ).');
      return this.extensions.get('WEBGL_compressed_texture_s3tc');
    },
    supportsCompressedTexturePVRTC: function() {
      console.warn('THREE.WebGLRenderer: .supportsCompressedTexturePVRTC() is now .extensions.get( \'WEBGL_compressed_texture_pvrtc\' ).');
      return this.extensions.get('WEBGL_compressed_texture_pvrtc');
    },
    supportsBlendMinMax: function() {
      console.warn('THREE.WebGLRenderer: .supportsBlendMinMax() is now .extensions.get( \'EXT_blend_minmax\' ).');
      return this.extensions.get('EXT_blend_minmax');
    },
    supportsVertexTextures: function() {
      return this.capabilities.vertexTextures;
    },
    supportsInstancedArrays: function() {
      console.warn('THREE.WebGLRenderer: .supportsInstancedArrays() is now .extensions.get( \'ANGLE_instanced_arrays\' ).');
      return this.extensions.get('ANGLE_instanced_arrays');
    },
    enableScissorTest: function(boolean) {
      console.warn('THREE.WebGLRenderer: .enableScissorTest() is now .setScissorTest().');
      this.setScissorTest(boolean);
    },
    initMaterial: function() {
      console.warn('THREE.WebGLRenderer: .initMaterial() has been removed.');
    },
    addPrePlugin: function() {
      console.warn('THREE.WebGLRenderer: .addPrePlugin() has been removed.');
    },
    addPostPlugin: function() {
      console.warn('THREE.WebGLRenderer: .addPostPlugin() has been removed.');
    },
    updateShadowMap: function() {
      console.warn('THREE.WebGLRenderer: .updateShadowMap() has been removed.');
    }
  });
  Object.defineProperties(THREE.WebGLRenderer.prototype, {
    shadowMapEnabled: {
      get: function() {
        return this.shadowMap.enabled;
      },
      set: function(value) {
        console.warn('THREE.WebGLRenderer: .shadowMapEnabled is now .shadowMap.enabled.');
        this.shadowMap.enabled = value;
      }
    },
    shadowMapType: {
      get: function() {
        return this.shadowMap.type;
      },
      set: function(value) {
        console.warn('THREE.WebGLRenderer: .shadowMapType is now .shadowMap.type.');
        this.shadowMap.type = value;
      }
    },
    shadowMapCullFace: {
      get: function() {
        return this.shadowMap.cullFace;
      },
      set: function(value) {
        console.warn('THREE.WebGLRenderer: .shadowMapCullFace is now .shadowMap.cullFace.');
        this.shadowMap.cullFace = value;
      }
    }
  });
  Object.defineProperties(THREE.WebGLShadowMap.prototype, {cullFace: {
      get: function() {
        return this.renderReverseSided ? THREE.CullFaceFront : THREE.CullFaceBack;
      },
      set: function(cullFace) {
        var value = (cullFace !== THREE.CullFaceBack);
        console.warn("WebGLRenderer: .shadowMap.cullFace is deprecated. Set .shadowMap.renderReverseSided to " + value + ".");
        this.renderReverseSided = value;
      }
    }});
  Object.defineProperties(THREE.WebGLRenderTarget.prototype, {
    wrapS: {
      get: function() {
        console.warn('THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.');
        return this.texture.wrapS;
      },
      set: function(value) {
        console.warn('THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.');
        this.texture.wrapS = value;
      }
    },
    wrapT: {
      get: function() {
        console.warn('THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.');
        return this.texture.wrapT;
      },
      set: function(value) {
        console.warn('THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.');
        this.texture.wrapT = value;
      }
    },
    magFilter: {
      get: function() {
        console.warn('THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.');
        return this.texture.magFilter;
      },
      set: function(value) {
        console.warn('THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.');
        this.texture.magFilter = value;
      }
    },
    minFilter: {
      get: function() {
        console.warn('THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.');
        return this.texture.minFilter;
      },
      set: function(value) {
        console.warn('THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.');
        this.texture.minFilter = value;
      }
    },
    anisotropy: {
      get: function() {
        console.warn('THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.');
        return this.texture.anisotropy;
      },
      set: function(value) {
        console.warn('THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.');
        this.texture.anisotropy = value;
      }
    },
    offset: {
      get: function() {
        console.warn('THREE.WebGLRenderTarget: .offset is now .texture.offset.');
        return this.texture.offset;
      },
      set: function(value) {
        console.warn('THREE.WebGLRenderTarget: .offset is now .texture.offset.');
        this.texture.offset = value;
      }
    },
    repeat: {
      get: function() {
        console.warn('THREE.WebGLRenderTarget: .repeat is now .texture.repeat.');
        return this.texture.repeat;
      },
      set: function(value) {
        console.warn('THREE.WebGLRenderTarget: .repeat is now .texture.repeat.');
        this.texture.repeat = value;
      }
    },
    format: {
      get: function() {
        console.warn('THREE.WebGLRenderTarget: .format is now .texture.format.');
        return this.texture.format;
      },
      set: function(value) {
        console.warn('THREE.WebGLRenderTarget: .format is now .texture.format.');
        this.texture.format = value;
      }
    },
    type: {
      get: function() {
        console.warn('THREE.WebGLRenderTarget: .type is now .texture.type.');
        return this.texture.type;
      },
      set: function(value) {
        console.warn('THREE.WebGLRenderTarget: .type is now .texture.type.');
        this.texture.type = value;
      }
    },
    generateMipmaps: {
      get: function() {
        console.warn('THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.');
        return this.texture.generateMipmaps;
      },
      set: function(value) {
        console.warn('THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.');
        this.texture.generateMipmaps = value;
      }
    }
  });
  Object.assign(THREE.Audio.prototype, {load: function(file) {
      console.warn('THREE.Audio: .load has been deprecated. Please use THREE.AudioLoader.');
      var scope = this;
      var audioLoader = new THREE.AudioLoader();
      audioLoader.load(file, function(buffer) {
        scope.setBuffer(buffer);
      });
      return this;
    }});
  Object.assign(THREE.AudioAnalyser.prototype, {getData: function(file) {
      console.warn('THREE.AudioAnalyser: .getData() is now .getFrequencyData().');
      return this.getFrequencyData();
    }});
  THREE.GeometryUtils = {
    merge: function(geometry1, geometry2, materialIndexOffset) {
      console.warn('THREE.GeometryUtils: .merge() has been moved to Geometry. Use geometry.merge( geometry2, matrix, materialIndexOffset ) instead.');
      var matrix;
      if (geometry2 instanceof THREE.Mesh) {
        geometry2.matrixAutoUpdate && geometry2.updateMatrix();
        matrix = geometry2.matrix;
        geometry2 = geometry2.geometry;
      }
      geometry1.merge(geometry2, matrix, materialIndexOffset);
    },
    center: function(geometry) {
      console.warn('THREE.GeometryUtils: .center() has been moved to Geometry. Use geometry.center() instead.');
      return geometry.center();
    }
  };
  THREE.ImageUtils = {
    crossOrigin: undefined,
    loadTexture: function(url, mapping, onLoad, onError) {
      console.warn('THREE.ImageUtils.loadTexture has been deprecated. Use THREE.TextureLoader() instead.');
      var loader = new THREE.TextureLoader();
      loader.setCrossOrigin(this.crossOrigin);
      var texture = loader.load(url, onLoad, undefined, onError);
      if (mapping)
        texture.mapping = mapping;
      return texture;
    },
    loadTextureCube: function(urls, mapping, onLoad, onError) {
      console.warn('THREE.ImageUtils.loadTextureCube has been deprecated. Use THREE.CubeTextureLoader() instead.');
      var loader = new THREE.CubeTextureLoader();
      loader.setCrossOrigin(this.crossOrigin);
      var texture = loader.load(urls, onLoad, undefined, onError);
      if (mapping)
        texture.mapping = mapping;
      return texture;
    },
    loadCompressedTexture: function() {
      console.error('THREE.ImageUtils.loadCompressedTexture has been removed. Use THREE.DDSLoader instead.');
    },
    loadCompressedTextureCube: function() {
      console.error('THREE.ImageUtils.loadCompressedTextureCube has been removed. Use THREE.DDSLoader instead.');
    }
  };
  THREE.Projector = function() {
    console.error('THREE.Projector has been moved to /examples/js/renderers/Projector.js.');
    this.projectVector = function(vector, camera) {
      console.warn('THREE.Projector: .projectVector() is now vector.project().');
      vector.project(camera);
    };
    this.unprojectVector = function(vector, camera) {
      console.warn('THREE.Projector: .unprojectVector() is now vector.unproject().');
      vector.unproject(camera);
    };
    this.pickingRay = function(vector, camera) {
      console.error('THREE.Projector: .pickingRay() is now raycaster.setFromCamera().');
    };
  };
  THREE.CanvasRenderer = function() {
    console.error('THREE.CanvasRenderer has been moved to /examples/js/renderers/CanvasRenderer.js');
    this.domElement = document.createElementNS('http://www.w3.org/1999/xhtml', 'canvas');
    this.clear = function() {};
    this.render = function() {};
    this.setClearColor = function() {};
    this.setSize = function() {};
  };
  THREE.CurveUtils = {
    tangentQuadraticBezier: function(t, p0, p1, p2) {
      return 2 * (1 - t) * (p1 - p0) + 2 * t * (p2 - p1);
    },
    tangentCubicBezier: function(t, p0, p1, p2, p3) {
      return -3 * p0 * (1 - t) * (1 - t) + 3 * p1 * (1 - t) * (1 - t) - 6 * t * p1 * (1 - t) + 6 * t * p2 * (1 - t) - 3 * t * t * p2 + 3 * t * t * p3;
    },
    tangentSpline: function(t, p0, p1, p2, p3) {
      var h00 = 6 * t * t - 6 * t;
      var h10 = 3 * t * t - 4 * t + 1;
      var h01 = -6 * t * t + 6 * t;
      var h11 = 3 * t * t - 2 * t;
      return h00 + h10 + h01 + h11;
    },
    interpolate: function(p0, p1, p2, p3, t) {
      var v0 = (p2 - p0) * 0.5;
      var v1 = (p3 - p1) * 0.5;
      var t2 = t * t;
      var t3 = t * t2;
      return (2 * p1 - 2 * p2 + v0 + v1) * t3 + (-3 * p1 + 3 * p2 - 2 * v0 - v1) * t2 + v0 * t + p1;
    }
  };
  THREE.SceneUtils = {
    createMultiMaterialObject: function(geometry, materials) {
      var group = new THREE.Group();
      for (var i = 0,
          l = materials.length; i < l; i++) {
        group.add(new THREE.Mesh(geometry, materials[i]));
      }
      return group;
    },
    detach: function(child, parent, scene) {
      child.applyMatrix(parent.matrixWorld);
      parent.remove(child);
      scene.add(child);
    },
    attach: function(child, scene, parent) {
      var matrixWorldInverse = new THREE.Matrix4();
      matrixWorldInverse.getInverse(parent.matrixWorld);
      child.applyMatrix(matrixWorldInverse);
      scene.remove(child);
      parent.add(child);
    }
  };
  THREE.ShapeUtils = {
    area: function(contour) {
      var n = contour.length;
      var a = 0.0;
      for (var p = n - 1,
          q = 0; q < n; p = q++) {
        a += contour[p].x * contour[q].y - contour[q].x * contour[p].y;
      }
      return a * 0.5;
    },
    triangulate: (function() {
      function snip(contour, u, v, w, n, verts) {
        var p;
        var ax,
            ay,
            bx,
            by;
        var cx,
            cy,
            px,
            py;
        ax = contour[verts[u]].x;
        ay = contour[verts[u]].y;
        bx = contour[verts[v]].x;
        by = contour[verts[v]].y;
        cx = contour[verts[w]].x;
        cy = contour[verts[w]].y;
        if (Number.EPSILON > (((bx - ax) * (cy - ay)) - ((by - ay) * (cx - ax))))
          return false;
        var aX,
            aY,
            bX,
            bY,
            cX,
            cY;
        var apx,
            apy,
            bpx,
            bpy,
            cpx,
            cpy;
        var cCROSSap,
            bCROSScp,
            aCROSSbp;
        aX = cx - bx;
        aY = cy - by;
        bX = ax - cx;
        bY = ay - cy;
        cX = bx - ax;
        cY = by - ay;
        for (p = 0; p < n; p++) {
          px = contour[verts[p]].x;
          py = contour[verts[p]].y;
          if (((px === ax) && (py === ay)) || ((px === bx) && (py === by)) || ((px === cx) && (py === cy)))
            continue;
          apx = px - ax;
          apy = py - ay;
          bpx = px - bx;
          bpy = py - by;
          cpx = px - cx;
          cpy = py - cy;
          aCROSSbp = aX * bpy - aY * bpx;
          cCROSSap = cX * apy - cY * apx;
          bCROSScp = bX * cpy - bY * cpx;
          if ((aCROSSbp >= -Number.EPSILON) && (bCROSScp >= -Number.EPSILON) && (cCROSSap >= -Number.EPSILON))
            return false;
        }
        return true;
      }
      return function triangulate(contour, indices) {
        var n = contour.length;
        if (n < 3)
          return null;
        var result = [],
            verts = [],
            vertIndices = [];
        var u,
            v,
            w;
        if (THREE.ShapeUtils.area(contour) > 0.0) {
          for (v = 0; v < n; v++)
            verts[v] = v;
        } else {
          for (v = 0; v < n; v++)
            verts[v] = (n - 1) - v;
        }
        var nv = n;
        var count = 2 * nv;
        for (v = nv - 1; nv > 2; ) {
          if ((count--) <= 0) {
            console.warn('THREE.ShapeUtils: Unable to triangulate polygon! in triangulate()');
            if (indices)
              return vertIndices;
            return result;
          }
          u = v;
          if (nv <= u)
            u = 0;
          v = u + 1;
          if (nv <= v)
            v = 0;
          w = v + 1;
          if (nv <= w)
            w = 0;
          if (snip(contour, u, v, w, nv, verts)) {
            var a,
                b,
                c,
                s,
                t;
            a = verts[u];
            b = verts[v];
            c = verts[w];
            result.push([contour[a], contour[b], contour[c]]);
            vertIndices.push([verts[u], verts[v], verts[w]]);
            for (s = v, t = v + 1; t < nv; s++, t++) {
              verts[s] = verts[t];
            }
            nv--;
            count = 2 * nv;
          }
        }
        if (indices)
          return vertIndices;
        return result;
      };
    })(),
    triangulateShape: function(contour, holes) {
      function point_in_segment_2D_colin(inSegPt1, inSegPt2, inOtherPt) {
        if (inSegPt1.x !== inSegPt2.x) {
          if (inSegPt1.x < inSegPt2.x) {
            return ((inSegPt1.x <= inOtherPt.x) && (inOtherPt.x <= inSegPt2.x));
          } else {
            return ((inSegPt2.x <= inOtherPt.x) && (inOtherPt.x <= inSegPt1.x));
          }
        } else {
          if (inSegPt1.y < inSegPt2.y) {
            return ((inSegPt1.y <= inOtherPt.y) && (inOtherPt.y <= inSegPt2.y));
          } else {
            return ((inSegPt2.y <= inOtherPt.y) && (inOtherPt.y <= inSegPt1.y));
          }
        }
      }
      function intersect_segments_2D(inSeg1Pt1, inSeg1Pt2, inSeg2Pt1, inSeg2Pt2, inExcludeAdjacentSegs) {
        var seg1dx = inSeg1Pt2.x - inSeg1Pt1.x,
            seg1dy = inSeg1Pt2.y - inSeg1Pt1.y;
        var seg2dx = inSeg2Pt2.x - inSeg2Pt1.x,
            seg2dy = inSeg2Pt2.y - inSeg2Pt1.y;
        var seg1seg2dx = inSeg1Pt1.x - inSeg2Pt1.x;
        var seg1seg2dy = inSeg1Pt1.y - inSeg2Pt1.y;
        var limit = seg1dy * seg2dx - seg1dx * seg2dy;
        var perpSeg1 = seg1dy * seg1seg2dx - seg1dx * seg1seg2dy;
        if (Math.abs(limit) > Number.EPSILON) {
          var perpSeg2;
          if (limit > 0) {
            if ((perpSeg1 < 0) || (perpSeg1 > limit))
              return [];
            perpSeg2 = seg2dy * seg1seg2dx - seg2dx * seg1seg2dy;
            if ((perpSeg2 < 0) || (perpSeg2 > limit))
              return [];
          } else {
            if ((perpSeg1 > 0) || (perpSeg1 < limit))
              return [];
            perpSeg2 = seg2dy * seg1seg2dx - seg2dx * seg1seg2dy;
            if ((perpSeg2 > 0) || (perpSeg2 < limit))
              return [];
          }
          if (perpSeg2 === 0) {
            if ((inExcludeAdjacentSegs) && ((perpSeg1 === 0) || (perpSeg1 === limit)))
              return [];
            return [inSeg1Pt1];
          }
          if (perpSeg2 === limit) {
            if ((inExcludeAdjacentSegs) && ((perpSeg1 === 0) || (perpSeg1 === limit)))
              return [];
            return [inSeg1Pt2];
          }
          if (perpSeg1 === 0)
            return [inSeg2Pt1];
          if (perpSeg1 === limit)
            return [inSeg2Pt2];
          var factorSeg1 = perpSeg2 / limit;
          return [{
            x: inSeg1Pt1.x + factorSeg1 * seg1dx,
            y: inSeg1Pt1.y + factorSeg1 * seg1dy
          }];
        } else {
          if ((perpSeg1 !== 0) || (seg2dy * seg1seg2dx !== seg2dx * seg1seg2dy))
            return [];
          var seg1Pt = ((seg1dx === 0) && (seg1dy === 0));
          var seg2Pt = ((seg2dx === 0) && (seg2dy === 0));
          if (seg1Pt && seg2Pt) {
            if ((inSeg1Pt1.x !== inSeg2Pt1.x) || (inSeg1Pt1.y !== inSeg2Pt1.y))
              return [];
            return [inSeg1Pt1];
          }
          if (seg1Pt) {
            if (!point_in_segment_2D_colin(inSeg2Pt1, inSeg2Pt2, inSeg1Pt1))
              return [];
            return [inSeg1Pt1];
          }
          if (seg2Pt) {
            if (!point_in_segment_2D_colin(inSeg1Pt1, inSeg1Pt2, inSeg2Pt1))
              return [];
            return [inSeg2Pt1];
          }
          var seg1min,
              seg1max,
              seg1minVal,
              seg1maxVal;
          var seg2min,
              seg2max,
              seg2minVal,
              seg2maxVal;
          if (seg1dx !== 0) {
            if (inSeg1Pt1.x < inSeg1Pt2.x) {
              seg1min = inSeg1Pt1;
              seg1minVal = inSeg1Pt1.x;
              seg1max = inSeg1Pt2;
              seg1maxVal = inSeg1Pt2.x;
            } else {
              seg1min = inSeg1Pt2;
              seg1minVal = inSeg1Pt2.x;
              seg1max = inSeg1Pt1;
              seg1maxVal = inSeg1Pt1.x;
            }
            if (inSeg2Pt1.x < inSeg2Pt2.x) {
              seg2min = inSeg2Pt1;
              seg2minVal = inSeg2Pt1.x;
              seg2max = inSeg2Pt2;
              seg2maxVal = inSeg2Pt2.x;
            } else {
              seg2min = inSeg2Pt2;
              seg2minVal = inSeg2Pt2.x;
              seg2max = inSeg2Pt1;
              seg2maxVal = inSeg2Pt1.x;
            }
          } else {
            if (inSeg1Pt1.y < inSeg1Pt2.y) {
              seg1min = inSeg1Pt1;
              seg1minVal = inSeg1Pt1.y;
              seg1max = inSeg1Pt2;
              seg1maxVal = inSeg1Pt2.y;
            } else {
              seg1min = inSeg1Pt2;
              seg1minVal = inSeg1Pt2.y;
              seg1max = inSeg1Pt1;
              seg1maxVal = inSeg1Pt1.y;
            }
            if (inSeg2Pt1.y < inSeg2Pt2.y) {
              seg2min = inSeg2Pt1;
              seg2minVal = inSeg2Pt1.y;
              seg2max = inSeg2Pt2;
              seg2maxVal = inSeg2Pt2.y;
            } else {
              seg2min = inSeg2Pt2;
              seg2minVal = inSeg2Pt2.y;
              seg2max = inSeg2Pt1;
              seg2maxVal = inSeg2Pt1.y;
            }
          }
          if (seg1minVal <= seg2minVal) {
            if (seg1maxVal < seg2minVal)
              return [];
            if (seg1maxVal === seg2minVal) {
              if (inExcludeAdjacentSegs)
                return [];
              return [seg2min];
            }
            if (seg1maxVal <= seg2maxVal)
              return [seg2min, seg1max];
            return [seg2min, seg2max];
          } else {
            if (seg1minVal > seg2maxVal)
              return [];
            if (seg1minVal === seg2maxVal) {
              if (inExcludeAdjacentSegs)
                return [];
              return [seg1min];
            }
            if (seg1maxVal <= seg2maxVal)
              return [seg1min, seg1max];
            return [seg1min, seg2max];
          }
        }
      }
      function isPointInsideAngle(inVertex, inLegFromPt, inLegToPt, inOtherPt) {
        var legFromPtX = inLegFromPt.x - inVertex.x,
            legFromPtY = inLegFromPt.y - inVertex.y;
        var legToPtX = inLegToPt.x - inVertex.x,
            legToPtY = inLegToPt.y - inVertex.y;
        var otherPtX = inOtherPt.x - inVertex.x,
            otherPtY = inOtherPt.y - inVertex.y;
        var from2toAngle = legFromPtX * legToPtY - legFromPtY * legToPtX;
        var from2otherAngle = legFromPtX * otherPtY - legFromPtY * otherPtX;
        if (Math.abs(from2toAngle) > Number.EPSILON) {
          var other2toAngle = otherPtX * legToPtY - otherPtY * legToPtX;
          if (from2toAngle > 0) {
            return ((from2otherAngle >= 0) && (other2toAngle >= 0));
          } else {
            return ((from2otherAngle >= 0) || (other2toAngle >= 0));
          }
        } else {
          return (from2otherAngle > 0);
        }
      }
      function removeHoles(contour, holes) {
        var shape = contour.concat();
        var hole;
        function isCutLineInsideAngles(inShapeIdx, inHoleIdx) {
          var lastShapeIdx = shape.length - 1;
          var prevShapeIdx = inShapeIdx - 1;
          if (prevShapeIdx < 0)
            prevShapeIdx = lastShapeIdx;
          var nextShapeIdx = inShapeIdx + 1;
          if (nextShapeIdx > lastShapeIdx)
            nextShapeIdx = 0;
          var insideAngle = isPointInsideAngle(shape[inShapeIdx], shape[prevShapeIdx], shape[nextShapeIdx], hole[inHoleIdx]);
          if (!insideAngle) {
            return false;
          }
          var lastHoleIdx = hole.length - 1;
          var prevHoleIdx = inHoleIdx - 1;
          if (prevHoleIdx < 0)
            prevHoleIdx = lastHoleIdx;
          var nextHoleIdx = inHoleIdx + 1;
          if (nextHoleIdx > lastHoleIdx)
            nextHoleIdx = 0;
          insideAngle = isPointInsideAngle(hole[inHoleIdx], hole[prevHoleIdx], hole[nextHoleIdx], shape[inShapeIdx]);
          if (!insideAngle) {
            return false;
          }
          return true;
        }
        function intersectsShapeEdge(inShapePt, inHolePt) {
          var sIdx,
              nextIdx,
              intersection;
          for (sIdx = 0; sIdx < shape.length; sIdx++) {
            nextIdx = sIdx + 1;
            nextIdx %= shape.length;
            intersection = intersect_segments_2D(inShapePt, inHolePt, shape[sIdx], shape[nextIdx], true);
            if (intersection.length > 0)
              return true;
          }
          return false;
        }
        var indepHoles = [];
        function intersectsHoleEdge(inShapePt, inHolePt) {
          var ihIdx,
              chkHole,
              hIdx,
              nextIdx,
              intersection;
          for (ihIdx = 0; ihIdx < indepHoles.length; ihIdx++) {
            chkHole = holes[indepHoles[ihIdx]];
            for (hIdx = 0; hIdx < chkHole.length; hIdx++) {
              nextIdx = hIdx + 1;
              nextIdx %= chkHole.length;
              intersection = intersect_segments_2D(inShapePt, inHolePt, chkHole[hIdx], chkHole[nextIdx], true);
              if (intersection.length > 0)
                return true;
            }
          }
          return false;
        }
        var holeIndex,
            shapeIndex,
            shapePt,
            holePt,
            holeIdx,
            cutKey,
            failedCuts = [],
            tmpShape1,
            tmpShape2,
            tmpHole1,
            tmpHole2;
        for (var h = 0,
            hl = holes.length; h < hl; h++) {
          indepHoles.push(h);
        }
        var minShapeIndex = 0;
        var counter = indepHoles.length * 2;
        while (indepHoles.length > 0) {
          counter--;
          if (counter < 0) {
            console.log("Infinite Loop! Holes left:" + indepHoles.length + ", Probably Hole outside Shape!");
            break;
          }
          for (shapeIndex = minShapeIndex; shapeIndex < shape.length; shapeIndex++) {
            shapePt = shape[shapeIndex];
            holeIndex = -1;
            for (var h = 0; h < indepHoles.length; h++) {
              holeIdx = indepHoles[h];
              cutKey = shapePt.x + ":" + shapePt.y + ":" + holeIdx;
              if (failedCuts[cutKey] !== undefined)
                continue;
              hole = holes[holeIdx];
              for (var h2 = 0; h2 < hole.length; h2++) {
                holePt = hole[h2];
                if (!isCutLineInsideAngles(shapeIndex, h2))
                  continue;
                if (intersectsShapeEdge(shapePt, holePt))
                  continue;
                if (intersectsHoleEdge(shapePt, holePt))
                  continue;
                holeIndex = h2;
                indepHoles.splice(h, 1);
                tmpShape1 = shape.slice(0, shapeIndex + 1);
                tmpShape2 = shape.slice(shapeIndex);
                tmpHole1 = hole.slice(holeIndex);
                tmpHole2 = hole.slice(0, holeIndex + 1);
                shape = tmpShape1.concat(tmpHole1).concat(tmpHole2).concat(tmpShape2);
                minShapeIndex = shapeIndex;
                break;
              }
              if (holeIndex >= 0)
                break;
              failedCuts[cutKey] = true;
            }
            if (holeIndex >= 0)
              break;
          }
        }
        return shape;
      }
      var i,
          il,
          f,
          face,
          key,
          index,
          allPointsMap = {};
      var allpoints = contour.concat();
      for (var h = 0,
          hl = holes.length; h < hl; h++) {
        Array.prototype.push.apply(allpoints, holes[h]);
      }
      for (i = 0, il = allpoints.length; i < il; i++) {
        key = allpoints[i].x + ":" + allpoints[i].y;
        if (allPointsMap[key] !== undefined) {
          console.warn("THREE.Shape: Duplicate point", key);
        }
        allPointsMap[key] = i;
      }
      var shapeWithoutHoles = removeHoles(contour, holes);
      var triangles = THREE.ShapeUtils.triangulate(shapeWithoutHoles, false);
      for (i = 0, il = triangles.length; i < il; i++) {
        face = triangles[i];
        for (f = 0; f < 3; f++) {
          key = face[f].x + ":" + face[f].y;
          index = allPointsMap[key];
          if (index !== undefined) {
            face[f] = index;
          }
        }
      }
      return triangles.concat();
    },
    isClockWise: function(pts) {
      return THREE.ShapeUtils.area(pts) < 0;
    },
    b2: (function() {
      function b2p0(t, p) {
        var k = 1 - t;
        return k * k * p;
      }
      function b2p1(t, p) {
        return 2 * (1 - t) * t * p;
      }
      function b2p2(t, p) {
        return t * t * p;
      }
      return function b2(t, p0, p1, p2) {
        return b2p0(t, p0) + b2p1(t, p1) + b2p2(t, p2);
      };
    })(),
    b3: (function() {
      function b3p0(t, p) {
        var k = 1 - t;
        return k * k * k * p;
      }
      function b3p1(t, p) {
        var k = 1 - t;
        return 3 * k * k * t * p;
      }
      function b3p2(t, p) {
        var k = 1 - t;
        return 3 * k * t * t * p;
      }
      function b3p3(t, p) {
        return t * t * t * p;
      }
      return function b3(t, p0, p1, p2, p3) {
        return b3p0(t, p0) + b3p1(t, p1) + b3p2(t, p2) + b3p3(t, p3);
      };
    })()
  };
  THREE.Curve = function() {};
  THREE.Curve.prototype = {
    constructor: THREE.Curve,
    getPoint: function(t) {
      console.warn("THREE.Curve: Warning, getPoint() not implemented!");
      return null;
    },
    getPointAt: function(u) {
      var t = this.getUtoTmapping(u);
      return this.getPoint(t);
    },
    getPoints: function(divisions) {
      if (!divisions)
        divisions = 5;
      var d,
          pts = [];
      for (d = 0; d <= divisions; d++) {
        pts.push(this.getPoint(d / divisions));
      }
      return pts;
    },
    getSpacedPoints: function(divisions) {
      if (!divisions)
        divisions = 5;
      var d,
          pts = [];
      for (d = 0; d <= divisions; d++) {
        pts.push(this.getPointAt(d / divisions));
      }
      return pts;
    },
    getLength: function() {
      var lengths = this.getLengths();
      return lengths[lengths.length - 1];
    },
    getLengths: function(divisions) {
      if (!divisions)
        divisions = (this.__arcLengthDivisions) ? (this.__arcLengthDivisions) : 200;
      if (this.cacheArcLengths && (this.cacheArcLengths.length === divisions + 1) && !this.needsUpdate) {
        return this.cacheArcLengths;
      }
      this.needsUpdate = false;
      var cache = [];
      var current,
          last = this.getPoint(0);
      var p,
          sum = 0;
      cache.push(0);
      for (p = 1; p <= divisions; p++) {
        current = this.getPoint(p / divisions);
        sum += current.distanceTo(last);
        cache.push(sum);
        last = current;
      }
      this.cacheArcLengths = cache;
      return cache;
    },
    updateArcLengths: function() {
      this.needsUpdate = true;
      this.getLengths();
    },
    getUtoTmapping: function(u, distance) {
      var arcLengths = this.getLengths();
      var i = 0,
          il = arcLengths.length;
      var targetArcLength;
      if (distance) {
        targetArcLength = distance;
      } else {
        targetArcLength = u * arcLengths[il - 1];
      }
      var low = 0,
          high = il - 1,
          comparison;
      while (low <= high) {
        i = Math.floor(low + (high - low) / 2);
        comparison = arcLengths[i] - targetArcLength;
        if (comparison < 0) {
          low = i + 1;
        } else if (comparison > 0) {
          high = i - 1;
        } else {
          high = i;
          break;
        }
      }
      i = high;
      if (arcLengths[i] === targetArcLength) {
        var t = i / (il - 1);
        return t;
      }
      var lengthBefore = arcLengths[i];
      var lengthAfter = arcLengths[i + 1];
      var segmentLength = lengthAfter - lengthBefore;
      var segmentFraction = (targetArcLength - lengthBefore) / segmentLength;
      var t = (i + segmentFraction) / (il - 1);
      return t;
    },
    getTangent: function(t) {
      var delta = 0.0001;
      var t1 = t - delta;
      var t2 = t + delta;
      if (t1 < 0)
        t1 = 0;
      if (t2 > 1)
        t2 = 1;
      var pt1 = this.getPoint(t1);
      var pt2 = this.getPoint(t2);
      var vec = pt2.clone().sub(pt1);
      return vec.normalize();
    },
    getTangentAt: function(u) {
      var t = this.getUtoTmapping(u);
      return this.getTangent(t);
    }
  };
  THREE.Curve.create = function(constructor, getPointFunc) {
    constructor.prototype = Object.create(THREE.Curve.prototype);
    constructor.prototype.constructor = constructor;
    constructor.prototype.getPoint = getPointFunc;
    return constructor;
  };
  THREE.CurvePath = function() {
    this.curves = [];
    this.autoClose = false;
  };
  THREE.CurvePath.prototype = Object.assign(Object.create(THREE.Curve.prototype), {
    constructor: THREE.CurvePath,
    add: function(curve) {
      this.curves.push(curve);
    },
    closePath: function() {
      var startPoint = this.curves[0].getPoint(0);
      var endPoint = this.curves[this.curves.length - 1].getPoint(1);
      if (!startPoint.equals(endPoint)) {
        this.curves.push(new THREE.LineCurve(endPoint, startPoint));
      }
    },
    getPoint: function(t) {
      var d = t * this.getLength();
      var curveLengths = this.getCurveLengths();
      var i = 0;
      while (i < curveLengths.length) {
        if (curveLengths[i] >= d) {
          var diff = curveLengths[i] - d;
          var curve = this.curves[i];
          var u = 1 - diff / curve.getLength();
          return curve.getPointAt(u);
        }
        i++;
      }
      return null;
    },
    getLength: function() {
      var lens = this.getCurveLengths();
      return lens[lens.length - 1];
    },
    updateArcLengths: function() {
      this.needsUpdate = true;
      this.cacheLengths = null;
      this.getLengths();
    },
    getCurveLengths: function() {
      if (this.cacheLengths && this.cacheLengths.length === this.curves.length) {
        return this.cacheLengths;
      }
      var lengths = [],
          sums = 0;
      for (var i = 0,
          l = this.curves.length; i < l; i++) {
        sums += this.curves[i].getLength();
        lengths.push(sums);
      }
      this.cacheLengths = lengths;
      return lengths;
    },
    createPointsGeometry: function(divisions) {
      var pts = this.getPoints(divisions);
      return this.createGeometry(pts);
    },
    createSpacedPointsGeometry: function(divisions) {
      var pts = this.getSpacedPoints(divisions);
      return this.createGeometry(pts);
    },
    createGeometry: function(points) {
      var geometry = new THREE.Geometry();
      for (var i = 0,
          l = points.length; i < l; i++) {
        var point = points[i];
        geometry.vertices.push(new THREE.Vector3(point.x, point.y, point.z || 0));
      }
      return geometry;
    }
  });
  THREE.Font = function(data) {
    this.data = data;
  };
  Object.assign(THREE.Font.prototype, {generateShapes: function(text, size, divisions) {
      function createPaths(text) {
        var chars = String(text).split('');
        var scale = size / data.resolution;
        var offset = 0;
        var paths = [];
        for (var i = 0; i < chars.length; i++) {
          var ret = createPath(chars[i], scale, offset);
          offset += ret.offset;
          paths.push(ret.path);
        }
        return paths;
      }
      function createPath(c, scale, offset) {
        var glyph = data.glyphs[c] || data.glyphs['?'];
        if (!glyph)
          return;
        var path = new THREE.Path();
        var pts = [],
            b2 = THREE.ShapeUtils.b2,
            b3 = THREE.ShapeUtils.b3;
        var x,
            y,
            cpx,
            cpy,
            cpx0,
            cpy0,
            cpx1,
            cpy1,
            cpx2,
            cpy2,
            laste;
        if (glyph.o) {
          var outline = glyph._cachedOutline || (glyph._cachedOutline = glyph.o.split(' '));
          for (var i = 0,
              l = outline.length; i < l; ) {
            var action = outline[i++];
            switch (action) {
              case 'm':
                x = outline[i++] * scale + offset;
                y = outline[i++] * scale;
                path.moveTo(x, y);
                break;
              case 'l':
                x = outline[i++] * scale + offset;
                y = outline[i++] * scale;
                path.lineTo(x, y);
                break;
              case 'q':
                cpx = outline[i++] * scale + offset;
                cpy = outline[i++] * scale;
                cpx1 = outline[i++] * scale + offset;
                cpy1 = outline[i++] * scale;
                path.quadraticCurveTo(cpx1, cpy1, cpx, cpy);
                laste = pts[pts.length - 1];
                if (laste) {
                  cpx0 = laste.x;
                  cpy0 = laste.y;
                  for (var i2 = 1; i2 <= divisions; i2++) {
                    var t = i2 / divisions;
                    b2(t, cpx0, cpx1, cpx);
                    b2(t, cpy0, cpy1, cpy);
                  }
                }
                break;
              case 'b':
                cpx = outline[i++] * scale + offset;
                cpy = outline[i++] * scale;
                cpx1 = outline[i++] * scale + offset;
                cpy1 = outline[i++] * scale;
                cpx2 = outline[i++] * scale + offset;
                cpy2 = outline[i++] * scale;
                path.bezierCurveTo(cpx1, cpy1, cpx2, cpy2, cpx, cpy);
                laste = pts[pts.length - 1];
                if (laste) {
                  cpx0 = laste.x;
                  cpy0 = laste.y;
                  for (var i2 = 1; i2 <= divisions; i2++) {
                    var t = i2 / divisions;
                    b3(t, cpx0, cpx1, cpx2, cpx);
                    b3(t, cpy0, cpy1, cpy2, cpy);
                  }
                }
                break;
            }
          }
        }
        return {
          offset: glyph.ha * scale,
          path: path
        };
      }
      if (size === undefined)
        size = 100;
      if (divisions === undefined)
        divisions = 4;
      var data = this.data;
      var paths = createPaths(text);
      var shapes = [];
      for (var p = 0,
          pl = paths.length; p < pl; p++) {
        Array.prototype.push.apply(shapes, paths[p].toShapes());
      }
      return shapes;
    }});
  THREE.Path = function(points) {
    THREE.CurvePath.call(this);
    this.actions = [];
    if (points) {
      this.fromPoints(points);
    }
  };
  THREE.Path.prototype = Object.assign(Object.create(THREE.CurvePath.prototype), {
    constructor: THREE.Path,
    fromPoints: function(vectors) {
      this.moveTo(vectors[0].x, vectors[0].y);
      for (var i = 1,
          l = vectors.length; i < l; i++) {
        this.lineTo(vectors[i].x, vectors[i].y);
      }
    },
    moveTo: function(x, y) {
      this.actions.push({
        action: 'moveTo',
        args: [x, y]
      });
    },
    lineTo: function(x, y) {
      var lastargs = this.actions[this.actions.length - 1].args;
      var x0 = lastargs[lastargs.length - 2];
      var y0 = lastargs[lastargs.length - 1];
      var curve = new THREE.LineCurve(new THREE.Vector2(x0, y0), new THREE.Vector2(x, y));
      this.curves.push(curve);
      this.actions.push({
        action: 'lineTo',
        args: [x, y]
      });
    },
    quadraticCurveTo: function(aCPx, aCPy, aX, aY) {
      var lastargs = this.actions[this.actions.length - 1].args;
      var x0 = lastargs[lastargs.length - 2];
      var y0 = lastargs[lastargs.length - 1];
      var curve = new THREE.QuadraticBezierCurve(new THREE.Vector2(x0, y0), new THREE.Vector2(aCPx, aCPy), new THREE.Vector2(aX, aY));
      this.curves.push(curve);
      this.actions.push({
        action: 'quadraticCurveTo',
        args: [aCPx, aCPy, aX, aY]
      });
    },
    bezierCurveTo: function(aCP1x, aCP1y, aCP2x, aCP2y, aX, aY) {
      var lastargs = this.actions[this.actions.length - 1].args;
      var x0 = lastargs[lastargs.length - 2];
      var y0 = lastargs[lastargs.length - 1];
      var curve = new THREE.CubicBezierCurve(new THREE.Vector2(x0, y0), new THREE.Vector2(aCP1x, aCP1y), new THREE.Vector2(aCP2x, aCP2y), new THREE.Vector2(aX, aY));
      this.curves.push(curve);
      this.actions.push({
        action: 'bezierCurveTo',
        args: [aCP1x, aCP1y, aCP2x, aCP2y, aX, aY]
      });
    },
    splineThru: function(pts) {
      var args = Array.prototype.slice.call(arguments);
      var lastargs = this.actions[this.actions.length - 1].args;
      var x0 = lastargs[lastargs.length - 2];
      var y0 = lastargs[lastargs.length - 1];
      var npts = [new THREE.Vector2(x0, y0)];
      Array.prototype.push.apply(npts, pts);
      var curve = new THREE.SplineCurve(npts);
      this.curves.push(curve);
      var lastPoint = pts[pts.length - 1];
      args.push(lastPoint.x);
      args.push(lastPoint.y);
      this.actions.push({
        action: 'splineThru',
        args: args
      });
    },
    arc: function(aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise) {
      var lastargs = this.actions[this.actions.length - 1].args;
      var x0 = lastargs[lastargs.length - 2];
      var y0 = lastargs[lastargs.length - 1];
      this.absarc(aX + x0, aY + y0, aRadius, aStartAngle, aEndAngle, aClockwise);
    },
    absarc: function(aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise) {
      this.absellipse(aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise);
    },
    ellipse: function(aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation) {
      var lastargs = this.actions[this.actions.length - 1].args;
      var x0 = lastargs[lastargs.length - 2];
      var y0 = lastargs[lastargs.length - 1];
      this.absellipse(aX + x0, aY + y0, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation);
    },
    absellipse: function(aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation) {
      var args = [aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation || 0];
      var curve = new THREE.EllipseCurve(aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation);
      this.curves.push(curve);
      var lastPoint = curve.getPoint(1);
      args.push(lastPoint.x);
      args.push(lastPoint.y);
      this.actions.push({
        action: 'ellipse',
        args: args
      });
    },
    getSpacedPoints: function(divisions) {
      if (!divisions)
        divisions = 40;
      var points = [];
      for (var i = 0; i < divisions; i++) {
        points.push(this.getPoint(i / divisions));
      }
      if (this.autoClose) {
        points.push(points[0]);
      }
      return points;
    },
    getPoints: function(divisions) {
      divisions = divisions || 12;
      var b2 = THREE.ShapeUtils.b2;
      var b3 = THREE.ShapeUtils.b3;
      var points = [];
      var cpx,
          cpy,
          cpx2,
          cpy2,
          cpx1,
          cpy1,
          cpx0,
          cpy0,
          laste,
          tx,
          ty;
      for (var i = 0,
          l = this.actions.length; i < l; i++) {
        var item = this.actions[i];
        var action = item.action;
        var args = item.args;
        switch (action) {
          case 'moveTo':
            points.push(new THREE.Vector2(args[0], args[1]));
            break;
          case 'lineTo':
            points.push(new THREE.Vector2(args[0], args[1]));
            break;
          case 'quadraticCurveTo':
            cpx = args[2];
            cpy = args[3];
            cpx1 = args[0];
            cpy1 = args[1];
            if (points.length > 0) {
              laste = points[points.length - 1];
              cpx0 = laste.x;
              cpy0 = laste.y;
            } else {
              laste = this.actions[i - 1].args;
              cpx0 = laste[laste.length - 2];
              cpy0 = laste[laste.length - 1];
            }
            for (var j = 1; j <= divisions; j++) {
              var t = j / divisions;
              tx = b2(t, cpx0, cpx1, cpx);
              ty = b2(t, cpy0, cpy1, cpy);
              points.push(new THREE.Vector2(tx, ty));
            }
            break;
          case 'bezierCurveTo':
            cpx = args[4];
            cpy = args[5];
            cpx1 = args[0];
            cpy1 = args[1];
            cpx2 = args[2];
            cpy2 = args[3];
            if (points.length > 0) {
              laste = points[points.length - 1];
              cpx0 = laste.x;
              cpy0 = laste.y;
            } else {
              laste = this.actions[i - 1].args;
              cpx0 = laste[laste.length - 2];
              cpy0 = laste[laste.length - 1];
            }
            for (var j = 1; j <= divisions; j++) {
              var t = j / divisions;
              tx = b3(t, cpx0, cpx1, cpx2, cpx);
              ty = b3(t, cpy0, cpy1, cpy2, cpy);
              points.push(new THREE.Vector2(tx, ty));
            }
            break;
          case 'splineThru':
            laste = this.actions[i - 1].args;
            var last = new THREE.Vector2(laste[laste.length - 2], laste[laste.length - 1]);
            var spts = [last];
            var n = divisions * args[0].length;
            spts = spts.concat(args[0]);
            var spline = new THREE.SplineCurve(spts);
            for (var j = 1; j <= n; j++) {
              points.push(spline.getPointAt(j / n));
            }
            break;
          case 'arc':
            var aX = args[0],
                aY = args[1],
                aRadius = args[2],
                aStartAngle = args[3],
                aEndAngle = args[4],
                aClockwise = !!args[5];
            var deltaAngle = aEndAngle - aStartAngle;
            var angle;
            var tdivisions = divisions * 2;
            for (var j = 1; j <= tdivisions; j++) {
              var t = j / tdivisions;
              if (!aClockwise) {
                t = 1 - t;
              }
              angle = aStartAngle + t * deltaAngle;
              tx = aX + aRadius * Math.cos(angle);
              ty = aY + aRadius * Math.sin(angle);
              points.push(new THREE.Vector2(tx, ty));
            }
            break;
          case 'ellipse':
            var aX = args[0],
                aY = args[1],
                xRadius = args[2],
                yRadius = args[3],
                aStartAngle = args[4],
                aEndAngle = args[5],
                aClockwise = !!args[6],
                aRotation = args[7];
            var deltaAngle = aEndAngle - aStartAngle;
            var angle;
            var tdivisions = divisions * 2;
            var cos,
                sin;
            if (aRotation !== 0) {
              cos = Math.cos(aRotation);
              sin = Math.sin(aRotation);
            }
            for (var j = 1; j <= tdivisions; j++) {
              var t = j / tdivisions;
              if (!aClockwise) {
                t = 1 - t;
              }
              angle = aStartAngle + t * deltaAngle;
              tx = aX + xRadius * Math.cos(angle);
              ty = aY + yRadius * Math.sin(angle);
              if (aRotation !== 0) {
                var x = tx,
                    y = ty;
                tx = (x - aX) * cos - (y - aY) * sin + aX;
                ty = (x - aX) * sin + (y - aY) * cos + aY;
              }
              points.push(new THREE.Vector2(tx, ty));
            }
            break;
        }
      }
      var lastPoint = points[points.length - 1];
      if (Math.abs(lastPoint.x - points[0].x) < Number.EPSILON && Math.abs(lastPoint.y - points[0].y) < Number.EPSILON)
        points.splice(points.length - 1, 1);
      if (this.autoClose) {
        points.push(points[0]);
      }
      return points;
    },
    toShapes: function(isCCW, noHoles) {
      function extractSubpaths(inActions) {
        var subPaths = [],
            lastPath = new THREE.Path();
        for (var i = 0,
            l = inActions.length; i < l; i++) {
          var item = inActions[i];
          var args = item.args;
          var action = item.action;
          if (action === 'moveTo') {
            if (lastPath.actions.length !== 0) {
              subPaths.push(lastPath);
              lastPath = new THREE.Path();
            }
          }
          lastPath[action].apply(lastPath, args);
        }
        if (lastPath.actions.length !== 0) {
          subPaths.push(lastPath);
        }
        return subPaths;
      }
      function toShapesNoHoles(inSubpaths) {
        var shapes = [];
        for (var i = 0,
            l = inSubpaths.length; i < l; i++) {
          var tmpPath = inSubpaths[i];
          var tmpShape = new THREE.Shape();
          tmpShape.actions = tmpPath.actions;
          tmpShape.curves = tmpPath.curves;
          shapes.push(tmpShape);
        }
        return shapes;
      }
      function isPointInsidePolygon(inPt, inPolygon) {
        var polyLen = inPolygon.length;
        var inside = false;
        for (var p = polyLen - 1,
            q = 0; q < polyLen; p = q++) {
          var edgeLowPt = inPolygon[p];
          var edgeHighPt = inPolygon[q];
          var edgeDx = edgeHighPt.x - edgeLowPt.x;
          var edgeDy = edgeHighPt.y - edgeLowPt.y;
          if (Math.abs(edgeDy) > Number.EPSILON) {
            if (edgeDy < 0) {
              edgeLowPt = inPolygon[q];
              edgeDx = -edgeDx;
              edgeHighPt = inPolygon[p];
              edgeDy = -edgeDy;
            }
            if ((inPt.y < edgeLowPt.y) || (inPt.y > edgeHighPt.y))
              continue;
            if (inPt.y === edgeLowPt.y) {
              if (inPt.x === edgeLowPt.x)
                return true;
            } else {
              var perpEdge = edgeDy * (inPt.x - edgeLowPt.x) - edgeDx * (inPt.y - edgeLowPt.y);
              if (perpEdge === 0)
                return true;
              if (perpEdge < 0)
                continue;
              inside = !inside;
            }
          } else {
            if (inPt.y !== edgeLowPt.y)
              continue;
            if (((edgeHighPt.x <= inPt.x) && (inPt.x <= edgeLowPt.x)) || ((edgeLowPt.x <= inPt.x) && (inPt.x <= edgeHighPt.x)))
              return true;
          }
        }
        return inside;
      }
      var isClockWise = THREE.ShapeUtils.isClockWise;
      var subPaths = extractSubpaths(this.actions);
      if (subPaths.length === 0)
        return [];
      if (noHoles === true)
        return toShapesNoHoles(subPaths);
      var solid,
          tmpPath,
          tmpShape,
          shapes = [];
      if (subPaths.length === 1) {
        tmpPath = subPaths[0];
        tmpShape = new THREE.Shape();
        tmpShape.actions = tmpPath.actions;
        tmpShape.curves = tmpPath.curves;
        shapes.push(tmpShape);
        return shapes;
      }
      var holesFirst = !isClockWise(subPaths[0].getPoints());
      holesFirst = isCCW ? !holesFirst : holesFirst;
      var betterShapeHoles = [];
      var newShapes = [];
      var newShapeHoles = [];
      var mainIdx = 0;
      var tmpPoints;
      newShapes[mainIdx] = undefined;
      newShapeHoles[mainIdx] = [];
      for (var i = 0,
          l = subPaths.length; i < l; i++) {
        tmpPath = subPaths[i];
        tmpPoints = tmpPath.getPoints();
        solid = isClockWise(tmpPoints);
        solid = isCCW ? !solid : solid;
        if (solid) {
          if ((!holesFirst) && (newShapes[mainIdx]))
            mainIdx++;
          newShapes[mainIdx] = {
            s: new THREE.Shape(),
            p: tmpPoints
          };
          newShapes[mainIdx].s.actions = tmpPath.actions;
          newShapes[mainIdx].s.curves = tmpPath.curves;
          if (holesFirst)
            mainIdx++;
          newShapeHoles[mainIdx] = [];
        } else {
          newShapeHoles[mainIdx].push({
            h: tmpPath,
            p: tmpPoints[0]
          });
        }
      }
      if (!newShapes[0])
        return toShapesNoHoles(subPaths);
      if (newShapes.length > 1) {
        var ambiguous = false;
        var toChange = [];
        for (var sIdx = 0,
            sLen = newShapes.length; sIdx < sLen; sIdx++) {
          betterShapeHoles[sIdx] = [];
        }
        for (var sIdx = 0,
            sLen = newShapes.length; sIdx < sLen; sIdx++) {
          var sho = newShapeHoles[sIdx];
          for (var hIdx = 0; hIdx < sho.length; hIdx++) {
            var ho = sho[hIdx];
            var hole_unassigned = true;
            for (var s2Idx = 0; s2Idx < newShapes.length; s2Idx++) {
              if (isPointInsidePolygon(ho.p, newShapes[s2Idx].p)) {
                if (sIdx !== s2Idx)
                  toChange.push({
                    froms: sIdx,
                    tos: s2Idx,
                    hole: hIdx
                  });
                if (hole_unassigned) {
                  hole_unassigned = false;
                  betterShapeHoles[s2Idx].push(ho);
                } else {
                  ambiguous = true;
                }
              }
            }
            if (hole_unassigned) {
              betterShapeHoles[sIdx].push(ho);
            }
          }
        }
        if (toChange.length > 0) {
          if (!ambiguous)
            newShapeHoles = betterShapeHoles;
        }
      }
      var tmpHoles;
      for (var i = 0,
          il = newShapes.length; i < il; i++) {
        tmpShape = newShapes[i].s;
        shapes.push(tmpShape);
        tmpHoles = newShapeHoles[i];
        for (var j = 0,
            jl = tmpHoles.length; j < jl; j++) {
          tmpShape.holes.push(tmpHoles[j].h);
        }
      }
      return shapes;
    }
  });
  THREE.Shape = function() {
    THREE.Path.apply(this, arguments);
    this.holes = [];
  };
  THREE.Shape.prototype = Object.assign(Object.create(THREE.Path.prototype), {
    constructor: THREE.Shape,
    extrude: function(options) {
      return new THREE.ExtrudeGeometry(this, options);
    },
    makeGeometry: function(options) {
      return new THREE.ShapeGeometry(this, options);
    },
    getPointsHoles: function(divisions) {
      var holesPts = [];
      for (var i = 0,
          l = this.holes.length; i < l; i++) {
        holesPts[i] = this.holes[i].getPoints(divisions);
      }
      return holesPts;
    },
    extractAllPoints: function(divisions) {
      return {
        shape: this.getPoints(divisions),
        holes: this.getPointsHoles(divisions)
      };
    },
    extractPoints: function(divisions) {
      return this.extractAllPoints(divisions);
    }
  });
  THREE.LineCurve = function(v1, v2) {
    this.v1 = v1;
    this.v2 = v2;
  };
  THREE.LineCurve.prototype = Object.create(THREE.Curve.prototype);
  THREE.LineCurve.prototype.constructor = THREE.LineCurve;
  THREE.LineCurve.prototype.getPoint = function(t) {
    var point = this.v2.clone().sub(this.v1);
    point.multiplyScalar(t).add(this.v1);
    return point;
  };
  THREE.LineCurve.prototype.getPointAt = function(u) {
    return this.getPoint(u);
  };
  THREE.LineCurve.prototype.getTangent = function(t) {
    var tangent = this.v2.clone().sub(this.v1);
    return tangent.normalize();
  };
  THREE.QuadraticBezierCurve = function(v0, v1, v2) {
    this.v0 = v0;
    this.v1 = v1;
    this.v2 = v2;
  };
  THREE.QuadraticBezierCurve.prototype = Object.create(THREE.Curve.prototype);
  THREE.QuadraticBezierCurve.prototype.constructor = THREE.QuadraticBezierCurve;
  THREE.QuadraticBezierCurve.prototype.getPoint = function(t) {
    var b2 = THREE.ShapeUtils.b2;
    return new THREE.Vector2(b2(t, this.v0.x, this.v1.x, this.v2.x), b2(t, this.v0.y, this.v1.y, this.v2.y));
  };
  THREE.QuadraticBezierCurve.prototype.getTangent = function(t) {
    var tangentQuadraticBezier = THREE.CurveUtils.tangentQuadraticBezier;
    return new THREE.Vector2(tangentQuadraticBezier(t, this.v0.x, this.v1.x, this.v2.x), tangentQuadraticBezier(t, this.v0.y, this.v1.y, this.v2.y)).normalize();
  };
  THREE.CubicBezierCurve = function(v0, v1, v2, v3) {
    this.v0 = v0;
    this.v1 = v1;
    this.v2 = v2;
    this.v3 = v3;
  };
  THREE.CubicBezierCurve.prototype = Object.create(THREE.Curve.prototype);
  THREE.CubicBezierCurve.prototype.constructor = THREE.CubicBezierCurve;
  THREE.CubicBezierCurve.prototype.getPoint = function(t) {
    var b3 = THREE.ShapeUtils.b3;
    return new THREE.Vector2(b3(t, this.v0.x, this.v1.x, this.v2.x, this.v3.x), b3(t, this.v0.y, this.v1.y, this.v2.y, this.v3.y));
  };
  THREE.CubicBezierCurve.prototype.getTangent = function(t) {
    var tangentCubicBezier = THREE.CurveUtils.tangentCubicBezier;
    return new THREE.Vector2(tangentCubicBezier(t, this.v0.x, this.v1.x, this.v2.x, this.v3.x), tangentCubicBezier(t, this.v0.y, this.v1.y, this.v2.y, this.v3.y)).normalize();
  };
  THREE.SplineCurve = function(points) {
    this.points = (points == undefined) ? [] : points;
  };
  THREE.SplineCurve.prototype = Object.create(THREE.Curve.prototype);
  THREE.SplineCurve.prototype.constructor = THREE.SplineCurve;
  THREE.SplineCurve.prototype.getPoint = function(t) {
    var points = this.points;
    var point = (points.length - 1) * t;
    var intPoint = Math.floor(point);
    var weight = point - intPoint;
    var point0 = points[intPoint === 0 ? intPoint : intPoint - 1];
    var point1 = points[intPoint];
    var point2 = points[intPoint > points.length - 2 ? points.length - 1 : intPoint + 1];
    var point3 = points[intPoint > points.length - 3 ? points.length - 1 : intPoint + 2];
    var interpolate = THREE.CurveUtils.interpolate;
    return new THREE.Vector2(interpolate(point0.x, point1.x, point2.x, point3.x, weight), interpolate(point0.y, point1.y, point2.y, point3.y, weight));
  };
  THREE.EllipseCurve = function(aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation) {
    this.aX = aX;
    this.aY = aY;
    this.xRadius = xRadius;
    this.yRadius = yRadius;
    this.aStartAngle = aStartAngle;
    this.aEndAngle = aEndAngle;
    this.aClockwise = aClockwise;
    this.aRotation = aRotation || 0;
  };
  THREE.EllipseCurve.prototype = Object.create(THREE.Curve.prototype);
  THREE.EllipseCurve.prototype.constructor = THREE.EllipseCurve;
  THREE.EllipseCurve.prototype.getPoint = function(t) {
    var deltaAngle = this.aEndAngle - this.aStartAngle;
    if (deltaAngle < 0)
      deltaAngle += Math.PI * 2;
    if (deltaAngle > Math.PI * 2)
      deltaAngle -= Math.PI * 2;
    var angle;
    if (this.aClockwise === true) {
      angle = this.aEndAngle + (1 - t) * (Math.PI * 2 - deltaAngle);
    } else {
      angle = this.aStartAngle + t * deltaAngle;
    }
    var x = this.aX + this.xRadius * Math.cos(angle);
    var y = this.aY + this.yRadius * Math.sin(angle);
    if (this.aRotation !== 0) {
      var cos = Math.cos(this.aRotation);
      var sin = Math.sin(this.aRotation);
      var tx = x,
          ty = y;
      x = (tx - this.aX) * cos - (ty - this.aY) * sin + this.aX;
      y = (tx - this.aX) * sin + (ty - this.aY) * cos + this.aY;
    }
    return new THREE.Vector2(x, y);
  };
  THREE.ArcCurve = function(aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise) {
    THREE.EllipseCurve.call(this, aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise);
  };
  THREE.ArcCurve.prototype = Object.create(THREE.EllipseCurve.prototype);
  THREE.ArcCurve.prototype.constructor = THREE.ArcCurve;
  THREE.LineCurve3 = THREE.Curve.create(function(v1, v2) {
    this.v1 = v1;
    this.v2 = v2;
  }, function(t) {
    var vector = new THREE.Vector3();
    vector.subVectors(this.v2, this.v1);
    vector.multiplyScalar(t);
    vector.add(this.v1);
    return vector;
  });
  THREE.QuadraticBezierCurve3 = THREE.Curve.create(function(v0, v1, v2) {
    this.v0 = v0;
    this.v1 = v1;
    this.v2 = v2;
  }, function(t) {
    var b2 = THREE.ShapeUtils.b2;
    return new THREE.Vector3(b2(t, this.v0.x, this.v1.x, this.v2.x), b2(t, this.v0.y, this.v1.y, this.v2.y), b2(t, this.v0.z, this.v1.z, this.v2.z));
  });
  THREE.CubicBezierCurve3 = THREE.Curve.create(function(v0, v1, v2, v3) {
    this.v0 = v0;
    this.v1 = v1;
    this.v2 = v2;
    this.v3 = v3;
  }, function(t) {
    var b3 = THREE.ShapeUtils.b3;
    return new THREE.Vector3(b3(t, this.v0.x, this.v1.x, this.v2.x, this.v3.x), b3(t, this.v0.y, this.v1.y, this.v2.y, this.v3.y), b3(t, this.v0.z, this.v1.z, this.v2.z, this.v3.z));
  });
  THREE.SplineCurve3 = THREE.Curve.create(function(points) {
    console.warn('THREE.SplineCurve3 will be deprecated. Please use THREE.CatmullRomCurve3');
    this.points = (points == undefined) ? [] : points;
  }, function(t) {
    var points = this.points;
    var point = (points.length - 1) * t;
    var intPoint = Math.floor(point);
    var weight = point - intPoint;
    var point0 = points[intPoint == 0 ? intPoint : intPoint - 1];
    var point1 = points[intPoint];
    var point2 = points[intPoint > points.length - 2 ? points.length - 1 : intPoint + 1];
    var point3 = points[intPoint > points.length - 3 ? points.length - 1 : intPoint + 2];
    var interpolate = THREE.CurveUtils.interpolate;
    return new THREE.Vector3(interpolate(point0.x, point1.x, point2.x, point3.x, weight), interpolate(point0.y, point1.y, point2.y, point3.y, weight), interpolate(point0.z, point1.z, point2.z, point3.z, weight));
  });
  THREE.CatmullRomCurve3 = (function() {
    var tmp = new THREE.Vector3(),
        px = new CubicPoly(),
        py = new CubicPoly(),
        pz = new CubicPoly();
    function CubicPoly() {}
    CubicPoly.prototype.init = function(x0, x1, t0, t1) {
      this.c0 = x0;
      this.c1 = t0;
      this.c2 = -3 * x0 + 3 * x1 - 2 * t0 - t1;
      this.c3 = 2 * x0 - 2 * x1 + t0 + t1;
    };
    CubicPoly.prototype.initNonuniformCatmullRom = function(x0, x1, x2, x3, dt0, dt1, dt2) {
      var t1 = (x1 - x0) / dt0 - (x2 - x0) / (dt0 + dt1) + (x2 - x1) / dt1;
      var t2 = (x2 - x1) / dt1 - (x3 - x1) / (dt1 + dt2) + (x3 - x2) / dt2;
      t1 *= dt1;
      t2 *= dt1;
      this.init(x1, x2, t1, t2);
    };
    CubicPoly.prototype.initCatmullRom = function(x0, x1, x2, x3, tension) {
      this.init(x1, x2, tension * (x2 - x0), tension * (x3 - x1));
    };
    CubicPoly.prototype.calc = function(t) {
      var t2 = t * t;
      var t3 = t2 * t;
      return this.c0 + this.c1 * t + this.c2 * t2 + this.c3 * t3;
    };
    return THREE.Curve.create(function(p) {
      this.points = p || [];
      this.closed = false;
    }, function(t) {
      var points = this.points,
          point,
          intPoint,
          weight,
          l;
      l = points.length;
      if (l < 2)
        console.log('duh, you need at least 2 points');
      point = (l - (this.closed ? 0 : 1)) * t;
      intPoint = Math.floor(point);
      weight = point - intPoint;
      if (this.closed) {
        intPoint += intPoint > 0 ? 0 : (Math.floor(Math.abs(intPoint) / points.length) + 1) * points.length;
      } else if (weight === 0 && intPoint === l - 1) {
        intPoint = l - 2;
        weight = 1;
      }
      var p0,
          p1,
          p2,
          p3;
      if (this.closed || intPoint > 0) {
        p0 = points[(intPoint - 1) % l];
      } else {
        tmp.subVectors(points[0], points[1]).add(points[0]);
        p0 = tmp;
      }
      p1 = points[intPoint % l];
      p2 = points[(intPoint + 1) % l];
      if (this.closed || intPoint + 2 < l) {
        p3 = points[(intPoint + 2) % l];
      } else {
        tmp.subVectors(points[l - 1], points[l - 2]).add(points[l - 1]);
        p3 = tmp;
      }
      if (this.type === undefined || this.type === 'centripetal' || this.type === 'chordal') {
        var pow = this.type === 'chordal' ? 0.5 : 0.25;
        var dt0 = Math.pow(p0.distanceToSquared(p1), pow);
        var dt1 = Math.pow(p1.distanceToSquared(p2), pow);
        var dt2 = Math.pow(p2.distanceToSquared(p3), pow);
        if (dt1 < 1e-4)
          dt1 = 1.0;
        if (dt0 < 1e-4)
          dt0 = dt1;
        if (dt2 < 1e-4)
          dt2 = dt1;
        px.initNonuniformCatmullRom(p0.x, p1.x, p2.x, p3.x, dt0, dt1, dt2);
        py.initNonuniformCatmullRom(p0.y, p1.y, p2.y, p3.y, dt0, dt1, dt2);
        pz.initNonuniformCatmullRom(p0.z, p1.z, p2.z, p3.z, dt0, dt1, dt2);
      } else if (this.type === 'catmullrom') {
        var tension = this.tension !== undefined ? this.tension : 0.5;
        px.initCatmullRom(p0.x, p1.x, p2.x, p3.x, tension);
        py.initCatmullRom(p0.y, p1.y, p2.y, p3.y, tension);
        pz.initCatmullRom(p0.z, p1.z, p2.z, p3.z, tension);
      }
      var v = new THREE.Vector3(px.calc(weight), py.calc(weight), pz.calc(weight));
      return v;
    });
  })();
  THREE.ClosedSplineCurve3 = function(points) {
    console.warn('THREE.ClosedSplineCurve3 has been deprecated. Please use THREE.CatmullRomCurve3.');
    THREE.CatmullRomCurve3.call(this, points);
    this.type = 'catmullrom';
    this.closed = true;
  };
  THREE.ClosedSplineCurve3.prototype = Object.create(THREE.CatmullRomCurve3.prototype);
  THREE.BoxGeometry = function(width, height, depth, widthSegments, heightSegments, depthSegments) {
    THREE.Geometry.call(this);
    this.type = 'BoxGeometry';
    this.parameters = {
      width: width,
      height: height,
      depth: depth,
      widthSegments: widthSegments,
      heightSegments: heightSegments,
      depthSegments: depthSegments
    };
    this.fromBufferGeometry(new THREE.BoxBufferGeometry(width, height, depth, widthSegments, heightSegments, depthSegments));
    this.mergeVertices();
  };
  THREE.BoxGeometry.prototype = Object.create(THREE.Geometry.prototype);
  THREE.BoxGeometry.prototype.constructor = THREE.BoxGeometry;
  THREE.CubeGeometry = THREE.BoxGeometry;
  THREE.BoxBufferGeometry = function(width, height, depth, widthSegments, heightSegments, depthSegments) {
    THREE.BufferGeometry.call(this);
    this.type = 'BoxBufferGeometry';
    this.parameters = {
      width: width,
      height: height,
      depth: depth,
      widthSegments: widthSegments,
      heightSegments: heightSegments,
      depthSegments: depthSegments
    };
    var scope = this;
    widthSegments = Math.floor(widthSegments) || 1;
    heightSegments = Math.floor(heightSegments) || 1;
    depthSegments = Math.floor(depthSegments) || 1;
    var vertexCount = calculateVertexCount(widthSegments, heightSegments, depthSegments);
    var indexCount = calculateIndexCount(widthSegments, heightSegments, depthSegments);
    var indices = new (indexCount > 65535 ? Uint32Array : Uint16Array)(indexCount);
    var vertices = new Float32Array(vertexCount * 3);
    var normals = new Float32Array(vertexCount * 3);
    var uvs = new Float32Array(vertexCount * 2);
    var vertexBufferOffset = 0;
    var uvBufferOffset = 0;
    var indexBufferOffset = 0;
    var numberOfVertices = 0;
    var groupStart = 0;
    buildPlane('z', 'y', 'x', -1, -1, depth, height, width, depthSegments, heightSegments, 0);
    buildPlane('z', 'y', 'x', 1, -1, depth, height, -width, depthSegments, heightSegments, 1);
    buildPlane('x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2);
    buildPlane('x', 'z', 'y', 1, -1, width, depth, -height, widthSegments, depthSegments, 3);
    buildPlane('x', 'y', 'z', 1, -1, width, height, depth, widthSegments, heightSegments, 4);
    buildPlane('x', 'y', 'z', -1, -1, width, height, -depth, widthSegments, heightSegments, 5);
    this.setIndex(new THREE.BufferAttribute(indices, 1));
    this.addAttribute('position', new THREE.BufferAttribute(vertices, 3));
    this.addAttribute('normal', new THREE.BufferAttribute(normals, 3));
    this.addAttribute('uv', new THREE.BufferAttribute(uvs, 2));
    function calculateVertexCount(w, h, d) {
      var vertices = 0;
      vertices += (w + 1) * (h + 1) * 2;
      vertices += (w + 1) * (d + 1) * 2;
      vertices += (d + 1) * (h + 1) * 2;
      return vertices;
    }
    function calculateIndexCount(w, h, d) {
      var index = 0;
      index += w * h * 2;
      index += w * d * 2;
      index += d * h * 2;
      return index * 6;
    }
    function buildPlane(u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex) {
      var segmentWidth = width / gridX;
      var segmentHeight = height / gridY;
      var widthHalf = width / 2;
      var heightHalf = height / 2;
      var depthHalf = depth / 2;
      var gridX1 = gridX + 1;
      var gridY1 = gridY + 1;
      var vertexCounter = 0;
      var groupCount = 0;
      var vector = new THREE.Vector3();
      for (var iy = 0; iy < gridY1; iy++) {
        var y = iy * segmentHeight - heightHalf;
        for (var ix = 0; ix < gridX1; ix++) {
          var x = ix * segmentWidth - widthHalf;
          vector[u] = x * udir;
          vector[v] = y * vdir;
          vector[w] = depthHalf;
          vertices[vertexBufferOffset] = vector.x;
          vertices[vertexBufferOffset + 1] = vector.y;
          vertices[vertexBufferOffset + 2] = vector.z;
          vector[u] = 0;
          vector[v] = 0;
          vector[w] = depth > 0 ? 1 : -1;
          normals[vertexBufferOffset] = vector.x;
          normals[vertexBufferOffset + 1] = vector.y;
          normals[vertexBufferOffset + 2] = vector.z;
          uvs[uvBufferOffset] = ix / gridX;
          uvs[uvBufferOffset + 1] = 1 - (iy / gridY);
          vertexBufferOffset += 3;
          uvBufferOffset += 2;
          vertexCounter += 1;
        }
      }
      for (iy = 0; iy < gridY; iy++) {
        for (ix = 0; ix < gridX; ix++) {
          var a = numberOfVertices + ix + gridX1 * iy;
          var b = numberOfVertices + ix + gridX1 * (iy + 1);
          var c = numberOfVertices + (ix + 1) + gridX1 * (iy + 1);
          var d = numberOfVertices + (ix + 1) + gridX1 * iy;
          indices[indexBufferOffset] = a;
          indices[indexBufferOffset + 1] = b;
          indices[indexBufferOffset + 2] = d;
          indices[indexBufferOffset + 3] = b;
          indices[indexBufferOffset + 4] = c;
          indices[indexBufferOffset + 5] = d;
          indexBufferOffset += 6;
          groupCount += 6;
        }
      }
      scope.addGroup(groupStart, groupCount, materialIndex);
      groupStart += groupCount;
      numberOfVertices += vertexCounter;
    }
  };
  THREE.BoxBufferGeometry.prototype = Object.create(THREE.BufferGeometry.prototype);
  THREE.BoxBufferGeometry.prototype.constructor = THREE.BoxBufferGeometry;
  THREE.CircleGeometry = function(radius, segments, thetaStart, thetaLength) {
    THREE.Geometry.call(this);
    this.type = 'CircleGeometry';
    this.parameters = {
      radius: radius,
      segments: segments,
      thetaStart: thetaStart,
      thetaLength: thetaLength
    };
    this.fromBufferGeometry(new THREE.CircleBufferGeometry(radius, segments, thetaStart, thetaLength));
  };
  THREE.CircleGeometry.prototype = Object.create(THREE.Geometry.prototype);
  THREE.CircleGeometry.prototype.constructor = THREE.CircleGeometry;
  THREE.CircleBufferGeometry = function(radius, segments, thetaStart, thetaLength) {
    THREE.BufferGeometry.call(this);
    this.type = 'CircleBufferGeometry';
    this.parameters = {
      radius: radius,
      segments: segments,
      thetaStart: thetaStart,
      thetaLength: thetaLength
    };
    radius = radius || 50;
    segments = segments !== undefined ? Math.max(3, segments) : 8;
    thetaStart = thetaStart !== undefined ? thetaStart : 0;
    thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2;
    var vertices = segments + 2;
    var positions = new Float32Array(vertices * 3);
    var normals = new Float32Array(vertices * 3);
    var uvs = new Float32Array(vertices * 2);
    normals[2] = 1.0;
    uvs[0] = 0.5;
    uvs[1] = 0.5;
    for (var s = 0,
        i = 3,
        ii = 2; s <= segments; s++, i += 3, ii += 2) {
      var segment = thetaStart + s / segments * thetaLength;
      positions[i] = radius * Math.cos(segment);
      positions[i + 1] = radius * Math.sin(segment);
      normals[i + 2] = 1;
      uvs[ii] = (positions[i] / radius + 1) / 2;
      uvs[ii + 1] = (positions[i + 1] / radius + 1) / 2;
    }
    var indices = [];
    for (var i = 1; i <= segments; i++) {
      indices.push(i, i + 1, 0);
    }
    this.setIndex(new THREE.BufferAttribute(new Uint16Array(indices), 1));
    this.addAttribute('position', new THREE.BufferAttribute(positions, 3));
    this.addAttribute('normal', new THREE.BufferAttribute(normals, 3));
    this.addAttribute('uv', new THREE.BufferAttribute(uvs, 2));
    this.boundingSphere = new THREE.Sphere(new THREE.Vector3(), radius);
  };
  THREE.CircleBufferGeometry.prototype = Object.create(THREE.BufferGeometry.prototype);
  THREE.CircleBufferGeometry.prototype.constructor = THREE.CircleBufferGeometry;
  THREE.CylinderBufferGeometry = function(radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength) {
    THREE.BufferGeometry.call(this);
    this.type = 'CylinderBufferGeometry';
    this.parameters = {
      radiusTop: radiusTop,
      radiusBottom: radiusBottom,
      height: height,
      radialSegments: radialSegments,
      heightSegments: heightSegments,
      openEnded: openEnded,
      thetaStart: thetaStart,
      thetaLength: thetaLength
    };
    var scope = this;
    radiusTop = radiusTop !== undefined ? radiusTop : 20;
    radiusBottom = radiusBottom !== undefined ? radiusBottom : 20;
    height = height !== undefined ? height : 100;
    radialSegments = Math.floor(radialSegments) || 8;
    heightSegments = Math.floor(heightSegments) || 1;
    openEnded = openEnded !== undefined ? openEnded : false;
    thetaStart = thetaStart !== undefined ? thetaStart : 0.0;
    thetaLength = thetaLength !== undefined ? thetaLength : 2.0 * Math.PI;
    var nbCap = 0;
    if (openEnded === false) {
      if (radiusTop > 0)
        nbCap++;
      if (radiusBottom > 0)
        nbCap++;
    }
    var vertexCount = calculateVertexCount();
    var indexCount = calculateIndexCount();
    var indices = new THREE.BufferAttribute(new (indexCount > 65535 ? Uint32Array : Uint16Array)(indexCount), 1);
    var vertices = new THREE.BufferAttribute(new Float32Array(vertexCount * 3), 3);
    var normals = new THREE.BufferAttribute(new Float32Array(vertexCount * 3), 3);
    var uvs = new THREE.BufferAttribute(new Float32Array(vertexCount * 2), 2);
    var index = 0,
        indexOffset = 0,
        indexArray = [],
        halfHeight = height / 2;
    var groupStart = 0;
    generateTorso();
    if (openEnded === false) {
      if (radiusTop > 0)
        generateCap(true);
      if (radiusBottom > 0)
        generateCap(false);
    }
    this.setIndex(indices);
    this.addAttribute('position', vertices);
    this.addAttribute('normal', normals);
    this.addAttribute('uv', uvs);
    function calculateVertexCount() {
      var count = (radialSegments + 1) * (heightSegments + 1);
      if (openEnded === false) {
        count += ((radialSegments + 1) * nbCap) + (radialSegments * nbCap);
      }
      return count;
    }
    function calculateIndexCount() {
      var count = radialSegments * heightSegments * 2 * 3;
      if (openEnded === false) {
        count += radialSegments * nbCap * 3;
      }
      return count;
    }
    function generateTorso() {
      var x,
          y;
      var normal = new THREE.Vector3();
      var vertex = new THREE.Vector3();
      var groupCount = 0;
      var tanTheta = (radiusBottom - radiusTop) / height;
      for (y = 0; y <= heightSegments; y++) {
        var indexRow = [];
        var v = y / heightSegments;
        var radius = v * (radiusBottom - radiusTop) + radiusTop;
        for (x = 0; x <= radialSegments; x++) {
          var u = x / radialSegments;
          vertex.x = radius * Math.sin(u * thetaLength + thetaStart);
          vertex.y = -v * height + halfHeight;
          vertex.z = radius * Math.cos(u * thetaLength + thetaStart);
          vertices.setXYZ(index, vertex.x, vertex.y, vertex.z);
          normal.copy(vertex);
          if ((radiusTop === 0 && y === 0) || (radiusBottom === 0 && y === heightSegments)) {
            normal.x = Math.sin(u * thetaLength + thetaStart);
            normal.z = Math.cos(u * thetaLength + thetaStart);
          }
          normal.setY(Math.sqrt(normal.x * normal.x + normal.z * normal.z) * tanTheta).normalize();
          normals.setXYZ(index, normal.x, normal.y, normal.z);
          uvs.setXY(index, u, 1 - v);
          indexRow.push(index);
          index++;
        }
        indexArray.push(indexRow);
      }
      for (x = 0; x < radialSegments; x++) {
        for (y = 0; y < heightSegments; y++) {
          var i1 = indexArray[y][x];
          var i2 = indexArray[y + 1][x];
          var i3 = indexArray[y + 1][x + 1];
          var i4 = indexArray[y][x + 1];
          indices.setX(indexOffset, i1);
          indexOffset++;
          indices.setX(indexOffset, i2);
          indexOffset++;
          indices.setX(indexOffset, i4);
          indexOffset++;
          indices.setX(indexOffset, i2);
          indexOffset++;
          indices.setX(indexOffset, i3);
          indexOffset++;
          indices.setX(indexOffset, i4);
          indexOffset++;
          groupCount += 6;
        }
      }
      scope.addGroup(groupStart, groupCount, 0);
      groupStart += groupCount;
    }
    function generateCap(top) {
      var x,
          centerIndexStart,
          centerIndexEnd;
      var uv = new THREE.Vector2();
      var vertex = new THREE.Vector3();
      var groupCount = 0;
      var radius = (top === true) ? radiusTop : radiusBottom;
      var sign = (top === true) ? 1 : -1;
      centerIndexStart = index;
      for (x = 1; x <= radialSegments; x++) {
        vertices.setXYZ(index, 0, halfHeight * sign, 0);
        normals.setXYZ(index, 0, sign, 0);
        uv.x = 0.5;
        uv.y = 0.5;
        uvs.setXY(index, uv.x, uv.y);
        index++;
      }
      centerIndexEnd = index;
      for (x = 0; x <= radialSegments; x++) {
        var u = x / radialSegments;
        var theta = u * thetaLength + thetaStart;
        var cosTheta = Math.cos(theta);
        var sinTheta = Math.sin(theta);
        vertex.x = radius * sinTheta;
        vertex.y = halfHeight * sign;
        vertex.z = radius * cosTheta;
        vertices.setXYZ(index, vertex.x, vertex.y, vertex.z);
        normals.setXYZ(index, 0, sign, 0);
        uv.x = (cosTheta * 0.5) + 0.5;
        uv.y = (sinTheta * 0.5 * sign) + 0.5;
        uvs.setXY(index, uv.x, uv.y);
        index++;
      }
      for (x = 0; x < radialSegments; x++) {
        var c = centerIndexStart + x;
        var i = centerIndexEnd + x;
        if (top === true) {
          indices.setX(indexOffset, i);
          indexOffset++;
          indices.setX(indexOffset, i + 1);
          indexOffset++;
          indices.setX(indexOffset, c);
          indexOffset++;
        } else {
          indices.setX(indexOffset, i + 1);
          indexOffset++;
          indices.setX(indexOffset, i);
          indexOffset++;
          indices.setX(indexOffset, c);
          indexOffset++;
        }
        groupCount += 3;
      }
      scope.addGroup(groupStart, groupCount, top === true ? 1 : 2);
      groupStart += groupCount;
    }
  };
  THREE.CylinderBufferGeometry.prototype = Object.create(THREE.BufferGeometry.prototype);
  THREE.CylinderBufferGeometry.prototype.constructor = THREE.CylinderBufferGeometry;
  THREE.CylinderGeometry = function(radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength) {
    THREE.Geometry.call(this);
    this.type = 'CylinderGeometry';
    this.parameters = {
      radiusTop: radiusTop,
      radiusBottom: radiusBottom,
      height: height,
      radialSegments: radialSegments,
      heightSegments: heightSegments,
      openEnded: openEnded,
      thetaStart: thetaStart,
      thetaLength: thetaLength
    };
    this.fromBufferGeometry(new THREE.CylinderBufferGeometry(radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength));
    this.mergeVertices();
  };
  THREE.CylinderGeometry.prototype = Object.create(THREE.Geometry.prototype);
  THREE.CylinderGeometry.prototype.constructor = THREE.CylinderGeometry;
  THREE.ConeBufferGeometry = function(radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength) {
    THREE.CylinderBufferGeometry.call(this, 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength);
    this.type = 'ConeBufferGeometry';
    this.parameters = {
      radius: radius,
      height: height,
      radialSegments: radialSegments,
      heightSegments: heightSegments,
      thetaStart: thetaStart,
      thetaLength: thetaLength
    };
  };
  THREE.ConeBufferGeometry.prototype = Object.create(THREE.BufferGeometry.prototype);
  THREE.ConeBufferGeometry.prototype.constructor = THREE.ConeBufferGeometry;
  THREE.ConeGeometry = function(radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength) {
    THREE.CylinderGeometry.call(this, 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength);
    this.type = 'ConeGeometry';
    this.parameters = {
      radius: radius,
      height: height,
      radialSegments: radialSegments,
      heightSegments: heightSegments,
      openEnded: openEnded,
      thetaStart: thetaStart,
      thetaLength: thetaLength
    };
  };
  THREE.ConeGeometry.prototype = Object.create(THREE.CylinderGeometry.prototype);
  THREE.ConeGeometry.prototype.constructor = THREE.ConeGeometry;
  THREE.EdgesGeometry = function(geometry, thresholdAngle) {
    THREE.BufferGeometry.call(this);
    thresholdAngle = (thresholdAngle !== undefined) ? thresholdAngle : 1;
    var thresholdDot = Math.cos(THREE.Math.DEG2RAD * thresholdAngle);
    var edge = [0, 0],
        hash = {};
    function sortFunction(a, b) {
      return a - b;
    }
    var keys = ['a', 'b', 'c'];
    var geometry2;
    if (geometry instanceof THREE.BufferGeometry) {
      geometry2 = new THREE.Geometry();
      geometry2.fromBufferGeometry(geometry);
    } else {
      geometry2 = geometry.clone();
    }
    geometry2.mergeVertices();
    geometry2.computeFaceNormals();
    var vertices = geometry2.vertices;
    var faces = geometry2.faces;
    for (var i = 0,
        l = faces.length; i < l; i++) {
      var face = faces[i];
      for (var j = 0; j < 3; j++) {
        edge[0] = face[keys[j]];
        edge[1] = face[keys[(j + 1) % 3]];
        edge.sort(sortFunction);
        var key = edge.toString();
        if (hash[key] === undefined) {
          hash[key] = {
            vert1: edge[0],
            vert2: edge[1],
            face1: i,
            face2: undefined
          };
        } else {
          hash[key].face2 = i;
        }
      }
    }
    var coords = [];
    for (var key in hash) {
      var h = hash[key];
      if (h.face2 === undefined || faces[h.face1].normal.dot(faces[h.face2].normal) <= thresholdDot) {
        var vertex = vertices[h.vert1];
        coords.push(vertex.x);
        coords.push(vertex.y);
        coords.push(vertex.z);
        vertex = vertices[h.vert2];
        coords.push(vertex.x);
        coords.push(vertex.y);
        coords.push(vertex.z);
      }
    }
    this.addAttribute('position', new THREE.BufferAttribute(new Float32Array(coords), 3));
  };
  THREE.EdgesGeometry.prototype = Object.create(THREE.BufferGeometry.prototype);
  THREE.EdgesGeometry.prototype.constructor = THREE.EdgesGeometry;
  THREE.ExtrudeGeometry = function(shapes, options) {
    if (typeof(shapes) === "undefined") {
      shapes = [];
      return;
    }
    THREE.Geometry.call(this);
    this.type = 'ExtrudeGeometry';
    shapes = Array.isArray(shapes) ? shapes : [shapes];
    this.addShapeList(shapes, options);
    this.computeFaceNormals();
  };
  THREE.ExtrudeGeometry.prototype = Object.create(THREE.Geometry.prototype);
  THREE.ExtrudeGeometry.prototype.constructor = THREE.ExtrudeGeometry;
  THREE.ExtrudeGeometry.prototype.addShapeList = function(shapes, options) {
    var sl = shapes.length;
    for (var s = 0; s < sl; s++) {
      var shape = shapes[s];
      this.addShape(shape, options);
    }
  };
  THREE.ExtrudeGeometry.prototype.addShape = function(shape, options) {
    var amount = options.amount !== undefined ? options.amount : 100;
    var bevelThickness = options.bevelThickness !== undefined ? options.bevelThickness : 6;
    var bevelSize = options.bevelSize !== undefined ? options.bevelSize : bevelThickness - 2;
    var bevelSegments = options.bevelSegments !== undefined ? options.bevelSegments : 3;
    var bevelEnabled = options.bevelEnabled !== undefined ? options.bevelEnabled : true;
    var curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12;
    var steps = options.steps !== undefined ? options.steps : 1;
    var extrudePath = options.extrudePath;
    var extrudePts,
        extrudeByPath = false;
    var uvgen = options.UVGenerator !== undefined ? options.UVGenerator : THREE.ExtrudeGeometry.WorldUVGenerator;
    var splineTube,
        binormal,
        normal,
        position2;
    if (extrudePath) {
      extrudePts = extrudePath.getSpacedPoints(steps);
      extrudeByPath = true;
      bevelEnabled = false;
      splineTube = options.frames !== undefined ? options.frames : new THREE.TubeGeometry.FrenetFrames(extrudePath, steps, false);
      binormal = new THREE.Vector3();
      normal = new THREE.Vector3();
      position2 = new THREE.Vector3();
    }
    if (!bevelEnabled) {
      bevelSegments = 0;
      bevelThickness = 0;
      bevelSize = 0;
    }
    var ahole,
        h,
        hl;
    var scope = this;
    var shapesOffset = this.vertices.length;
    var shapePoints = shape.extractPoints(curveSegments);
    var vertices = shapePoints.shape;
    var holes = shapePoints.holes;
    var reverse = !THREE.ShapeUtils.isClockWise(vertices);
    if (reverse) {
      vertices = vertices.reverse();
      for (h = 0, hl = holes.length; h < hl; h++) {
        ahole = holes[h];
        if (THREE.ShapeUtils.isClockWise(ahole)) {
          holes[h] = ahole.reverse();
        }
      }
      reverse = false;
    }
    var faces = THREE.ShapeUtils.triangulateShape(vertices, holes);
    var contour = vertices;
    for (h = 0, hl = holes.length; h < hl; h++) {
      ahole = holes[h];
      vertices = vertices.concat(ahole);
    }
    function scalePt2(pt, vec, size) {
      if (!vec)
        console.error("THREE.ExtrudeGeometry: vec does not exist");
      return vec.clone().multiplyScalar(size).add(pt);
    }
    var b,
        bs,
        t,
        z,
        vert,
        vlen = vertices.length,
        face,
        flen = faces.length;
    function getBevelVec(inPt, inPrev, inNext) {
      var v_trans_x,
          v_trans_y,
          shrink_by = 1;
      var v_prev_x = inPt.x - inPrev.x,
          v_prev_y = inPt.y - inPrev.y;
      var v_next_x = inNext.x - inPt.x,
          v_next_y = inNext.y - inPt.y;
      var v_prev_lensq = (v_prev_x * v_prev_x + v_prev_y * v_prev_y);
      var collinear0 = (v_prev_x * v_next_y - v_prev_y * v_next_x);
      if (Math.abs(collinear0) > Number.EPSILON) {
        var v_prev_len = Math.sqrt(v_prev_lensq);
        var v_next_len = Math.sqrt(v_next_x * v_next_x + v_next_y * v_next_y);
        var ptPrevShift_x = (inPrev.x - v_prev_y / v_prev_len);
        var ptPrevShift_y = (inPrev.y + v_prev_x / v_prev_len);
        var ptNextShift_x = (inNext.x - v_next_y / v_next_len);
        var ptNextShift_y = (inNext.y + v_next_x / v_next_len);
        var sf = ((ptNextShift_x - ptPrevShift_x) * v_next_y - (ptNextShift_y - ptPrevShift_y) * v_next_x) / (v_prev_x * v_next_y - v_prev_y * v_next_x);
        v_trans_x = (ptPrevShift_x + v_prev_x * sf - inPt.x);
        v_trans_y = (ptPrevShift_y + v_prev_y * sf - inPt.y);
        var v_trans_lensq = (v_trans_x * v_trans_x + v_trans_y * v_trans_y);
        if (v_trans_lensq <= 2) {
          return new THREE.Vector2(v_trans_x, v_trans_y);
        } else {
          shrink_by = Math.sqrt(v_trans_lensq / 2);
        }
      } else {
        var direction_eq = false;
        if (v_prev_x > Number.EPSILON) {
          if (v_next_x > Number.EPSILON) {
            direction_eq = true;
          }
        } else {
          if (v_prev_x < -Number.EPSILON) {
            if (v_next_x < -Number.EPSILON) {
              direction_eq = true;
            }
          } else {
            if (Math.sign(v_prev_y) === Math.sign(v_next_y)) {
              direction_eq = true;
            }
          }
        }
        if (direction_eq) {
          v_trans_x = -v_prev_y;
          v_trans_y = v_prev_x;
          shrink_by = Math.sqrt(v_prev_lensq);
        } else {
          v_trans_x = v_prev_x;
          v_trans_y = v_prev_y;
          shrink_by = Math.sqrt(v_prev_lensq / 2);
        }
      }
      return new THREE.Vector2(v_trans_x / shrink_by, v_trans_y / shrink_by);
    }
    var contourMovements = [];
    for (var i = 0,
        il = contour.length,
        j = il - 1,
        k = i + 1; i < il; i++, j++, k++) {
      if (j === il)
        j = 0;
      if (k === il)
        k = 0;
      contourMovements[i] = getBevelVec(contour[i], contour[j], contour[k]);
    }
    var holesMovements = [],
        oneHoleMovements,
        verticesMovements = contourMovements.concat();
    for (h = 0, hl = holes.length; h < hl; h++) {
      ahole = holes[h];
      oneHoleMovements = [];
      for (i = 0, il = ahole.length, j = il - 1, k = i + 1; i < il; i++, j++, k++) {
        if (j === il)
          j = 0;
        if (k === il)
          k = 0;
        oneHoleMovements[i] = getBevelVec(ahole[i], ahole[j], ahole[k]);
      }
      holesMovements.push(oneHoleMovements);
      verticesMovements = verticesMovements.concat(oneHoleMovements);
    }
    for (b = 0; b < bevelSegments; b++) {
      t = b / bevelSegments;
      z = bevelThickness * (1 - t);
      bs = bevelSize * (Math.sin(t * Math.PI / 2));
      for (i = 0, il = contour.length; i < il; i++) {
        vert = scalePt2(contour[i], contourMovements[i], bs);
        v(vert.x, vert.y, -z);
      }
      for (h = 0, hl = holes.length; h < hl; h++) {
        ahole = holes[h];
        oneHoleMovements = holesMovements[h];
        for (i = 0, il = ahole.length; i < il; i++) {
          vert = scalePt2(ahole[i], oneHoleMovements[i], bs);
          v(vert.x, vert.y, -z);
        }
      }
    }
    bs = bevelSize;
    for (i = 0; i < vlen; i++) {
      vert = bevelEnabled ? scalePt2(vertices[i], verticesMovements[i], bs) : vertices[i];
      if (!extrudeByPath) {
        v(vert.x, vert.y, 0);
      } else {
        normal.copy(splineTube.normals[0]).multiplyScalar(vert.x);
        binormal.copy(splineTube.binormals[0]).multiplyScalar(vert.y);
        position2.copy(extrudePts[0]).add(normal).add(binormal);
        v(position2.x, position2.y, position2.z);
      }
    }
    var s;
    for (s = 1; s <= steps; s++) {
      for (i = 0; i < vlen; i++) {
        vert = bevelEnabled ? scalePt2(vertices[i], verticesMovements[i], bs) : vertices[i];
        if (!extrudeByPath) {
          v(vert.x, vert.y, amount / steps * s);
        } else {
          normal.copy(splineTube.normals[s]).multiplyScalar(vert.x);
          binormal.copy(splineTube.binormals[s]).multiplyScalar(vert.y);
          position2.copy(extrudePts[s]).add(normal).add(binormal);
          v(position2.x, position2.y, position2.z);
        }
      }
    }
    for (b = bevelSegments - 1; b >= 0; b--) {
      t = b / bevelSegments;
      z = bevelThickness * (1 - t);
      bs = bevelSize * Math.sin(t * Math.PI / 2);
      for (i = 0, il = contour.length; i < il; i++) {
        vert = scalePt2(contour[i], contourMovements[i], bs);
        v(vert.x, vert.y, amount + z);
      }
      for (h = 0, hl = holes.length; h < hl; h++) {
        ahole = holes[h];
        oneHoleMovements = holesMovements[h];
        for (i = 0, il = ahole.length; i < il; i++) {
          vert = scalePt2(ahole[i], oneHoleMovements[i], bs);
          if (!extrudeByPath) {
            v(vert.x, vert.y, amount + z);
          } else {
            v(vert.x, vert.y + extrudePts[steps - 1].y, extrudePts[steps - 1].x + z);
          }
        }
      }
    }
    buildLidFaces();
    buildSideFaces();
    function buildLidFaces() {
      if (bevelEnabled) {
        var layer = 0;
        var offset = vlen * layer;
        for (i = 0; i < flen; i++) {
          face = faces[i];
          f3(face[2] + offset, face[1] + offset, face[0] + offset);
        }
        layer = steps + bevelSegments * 2;
        offset = vlen * layer;
        for (i = 0; i < flen; i++) {
          face = faces[i];
          f3(face[0] + offset, face[1] + offset, face[2] + offset);
        }
      } else {
        for (i = 0; i < flen; i++) {
          face = faces[i];
          f3(face[2], face[1], face[0]);
        }
        for (i = 0; i < flen; i++) {
          face = faces[i];
          f3(face[0] + vlen * steps, face[1] + vlen * steps, face[2] + vlen * steps);
        }
      }
    }
    function buildSideFaces() {
      var layeroffset = 0;
      sidewalls(contour, layeroffset);
      layeroffset += contour.length;
      for (h = 0, hl = holes.length; h < hl; h++) {
        ahole = holes[h];
        sidewalls(ahole, layeroffset);
        layeroffset += ahole.length;
      }
    }
    function sidewalls(contour, layeroffset) {
      var j,
          k;
      i = contour.length;
      while (--i >= 0) {
        j = i;
        k = i - 1;
        if (k < 0)
          k = contour.length - 1;
        var s = 0,
            sl = steps + bevelSegments * 2;
        for (s = 0; s < sl; s++) {
          var slen1 = vlen * s;
          var slen2 = vlen * (s + 1);
          var a = layeroffset + j + slen1,
              b = layeroffset + k + slen1,
              c = layeroffset + k + slen2,
              d = layeroffset + j + slen2;
          f4(a, b, c, d, contour, s, sl, j, k);
        }
      }
    }
    function v(x, y, z) {
      scope.vertices.push(new THREE.Vector3(x, y, z));
    }
    function f3(a, b, c) {
      a += shapesOffset;
      b += shapesOffset;
      c += shapesOffset;
      scope.faces.push(new THREE.Face3(a, b, c, null, null, 0));
      var uvs = uvgen.generateTopUV(scope, a, b, c);
      scope.faceVertexUvs[0].push(uvs);
    }
    function f4(a, b, c, d, wallContour, stepIndex, stepsLength, contourIndex1, contourIndex2) {
      a += shapesOffset;
      b += shapesOffset;
      c += shapesOffset;
      d += shapesOffset;
      scope.faces.push(new THREE.Face3(a, b, d, null, null, 1));
      scope.faces.push(new THREE.Face3(b, c, d, null, null, 1));
      var uvs = uvgen.generateSideWallUV(scope, a, b, c, d);
      scope.faceVertexUvs[0].push([uvs[0], uvs[1], uvs[3]]);
      scope.faceVertexUvs[0].push([uvs[1], uvs[2], uvs[3]]);
    }
  };
  THREE.ExtrudeGeometry.WorldUVGenerator = {
    generateTopUV: function(geometry, indexA, indexB, indexC) {
      var vertices = geometry.vertices;
      var a = vertices[indexA];
      var b = vertices[indexB];
      var c = vertices[indexC];
      return [new THREE.Vector2(a.x, a.y), new THREE.Vector2(b.x, b.y), new THREE.Vector2(c.x, c.y)];
    },
    generateSideWallUV: function(geometry, indexA, indexB, indexC, indexD) {
      var vertices = geometry.vertices;
      var a = vertices[indexA];
      var b = vertices[indexB];
      var c = vertices[indexC];
      var d = vertices[indexD];
      if (Math.abs(a.y - b.y) < 0.01) {
        return [new THREE.Vector2(a.x, 1 - a.z), new THREE.Vector2(b.x, 1 - b.z), new THREE.Vector2(c.x, 1 - c.z), new THREE.Vector2(d.x, 1 - d.z)];
      } else {
        return [new THREE.Vector2(a.y, 1 - a.z), new THREE.Vector2(b.y, 1 - b.z), new THREE.Vector2(c.y, 1 - c.z), new THREE.Vector2(d.y, 1 - d.z)];
      }
    }
  };
  THREE.ShapeGeometry = function(shapes, options) {
    THREE.Geometry.call(this);
    this.type = 'ShapeGeometry';
    if (Array.isArray(shapes) === false)
      shapes = [shapes];
    this.addShapeList(shapes, options);
    this.computeFaceNormals();
  };
  THREE.ShapeGeometry.prototype = Object.create(THREE.Geometry.prototype);
  THREE.ShapeGeometry.prototype.constructor = THREE.ShapeGeometry;
  THREE.ShapeGeometry.prototype.addShapeList = function(shapes, options) {
    for (var i = 0,
        l = shapes.length; i < l; i++) {
      this.addShape(shapes[i], options);
    }
    return this;
  };
  THREE.ShapeGeometry.prototype.addShape = function(shape, options) {
    if (options === undefined)
      options = {};
    var curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12;
    var material = options.material;
    var uvgen = options.UVGenerator === undefined ? THREE.ExtrudeGeometry.WorldUVGenerator : options.UVGenerator;
    var i,
        l,
        hole;
    var shapesOffset = this.vertices.length;
    var shapePoints = shape.extractPoints(curveSegments);
    var vertices = shapePoints.shape;
    var holes = shapePoints.holes;
    var reverse = !THREE.ShapeUtils.isClockWise(vertices);
    if (reverse) {
      vertices = vertices.reverse();
      for (i = 0, l = holes.length; i < l; i++) {
        hole = holes[i];
        if (THREE.ShapeUtils.isClockWise(hole)) {
          holes[i] = hole.reverse();
        }
      }
      reverse = false;
    }
    var faces = THREE.ShapeUtils.triangulateShape(vertices, holes);
    for (i = 0, l = holes.length; i < l; i++) {
      hole = holes[i];
      vertices = vertices.concat(hole);
    }
    var vert,
        vlen = vertices.length;
    var face,
        flen = faces.length;
    for (i = 0; i < vlen; i++) {
      vert = vertices[i];
      this.vertices.push(new THREE.Vector3(vert.x, vert.y, 0));
    }
    for (i = 0; i < flen; i++) {
      face = faces[i];
      var a = face[0] + shapesOffset;
      var b = face[1] + shapesOffset;
      var c = face[2] + shapesOffset;
      this.faces.push(new THREE.Face3(a, b, c, null, null, material));
      this.faceVertexUvs[0].push(uvgen.generateTopUV(this, a, b, c));
    }
  };
  THREE.LatheBufferGeometry = function(points, segments, phiStart, phiLength) {
    THREE.BufferGeometry.call(this);
    this.type = 'LatheBufferGeometry';
    this.parameters = {
      points: points,
      segments: segments,
      phiStart: phiStart,
      phiLength: phiLength
    };
    segments = Math.floor(segments) || 12;
    phiStart = phiStart || 0;
    phiLength = phiLength || Math.PI * 2;
    phiLength = THREE.Math.clamp(phiLength, 0, Math.PI * 2);
    var vertexCount = (segments + 1) * points.length;
    var indexCount = segments * points.length * 2 * 3;
    var indices = new THREE.BufferAttribute(new (indexCount > 65535 ? Uint32Array : Uint16Array)(indexCount), 1);
    var vertices = new THREE.BufferAttribute(new Float32Array(vertexCount * 3), 3);
    var uvs = new THREE.BufferAttribute(new Float32Array(vertexCount * 2), 2);
    var index = 0,
        indexOffset = 0,
        base;
    var inversePointLength = 1.0 / (points.length - 1);
    var inverseSegments = 1.0 / segments;
    var vertex = new THREE.Vector3();
    var uv = new THREE.Vector2();
    var i,
        j;
    for (i = 0; i <= segments; i++) {
      var phi = phiStart + i * inverseSegments * phiLength;
      var sin = Math.sin(phi);
      var cos = Math.cos(phi);
      for (j = 0; j <= (points.length - 1); j++) {
        vertex.x = points[j].x * sin;
        vertex.y = points[j].y;
        vertex.z = points[j].x * cos;
        vertices.setXYZ(index, vertex.x, vertex.y, vertex.z);
        uv.x = i / segments;
        uv.y = j / (points.length - 1);
        uvs.setXY(index, uv.x, uv.y);
        index++;
      }
    }
    for (i = 0; i < segments; i++) {
      for (j = 0; j < (points.length - 1); j++) {
        base = j + i * points.length;
        var a = base;
        var b = base + points.length;
        var c = base + points.length + 1;
        var d = base + 1;
        indices.setX(indexOffset, a);
        indexOffset++;
        indices.setX(indexOffset, b);
        indexOffset++;
        indices.setX(indexOffset, d);
        indexOffset++;
        indices.setX(indexOffset, b);
        indexOffset++;
        indices.setX(indexOffset, c);
        indexOffset++;
        indices.setX(indexOffset, d);
        indexOffset++;
      }
    }
    this.setIndex(indices);
    this.addAttribute('position', vertices);
    this.addAttribute('uv', uvs);
    this.computeVertexNormals();
    if (phiLength === Math.PI * 2) {
      var normals = this.attributes.normal.array;
      var n1 = new THREE.Vector3();
      var n2 = new THREE.Vector3();
      var n = new THREE.Vector3();
      base = segments * points.length * 3;
      for (i = 0, j = 0; i < points.length; i++, j += 3) {
        n1.x = normals[j + 0];
        n1.y = normals[j + 1];
        n1.z = normals[j + 2];
        n2.x = normals[base + j + 0];
        n2.y = normals[base + j + 1];
        n2.z = normals[base + j + 2];
        n.addVectors(n1, n2).normalize();
        normals[j + 0] = normals[base + j + 0] = n.x;
        normals[j + 1] = normals[base + j + 1] = n.y;
        normals[j + 2] = normals[base + j + 2] = n.z;
      }
    }
  };
  THREE.LatheBufferGeometry.prototype = Object.create(THREE.BufferGeometry.prototype);
  THREE.LatheBufferGeometry.prototype.constructor = THREE.LatheBufferGeometry;
  THREE.LatheGeometry = function(points, segments, phiStart, phiLength) {
    THREE.Geometry.call(this);
    this.type = 'LatheGeometry';
    this.parameters = {
      points: points,
      segments: segments,
      phiStart: phiStart,
      phiLength: phiLength
    };
    this.fromBufferGeometry(new THREE.LatheBufferGeometry(points, segments, phiStart, phiLength));
    this.mergeVertices();
  };
  THREE.LatheGeometry.prototype = Object.create(THREE.Geometry.prototype);
  THREE.LatheGeometry.prototype.constructor = THREE.LatheGeometry;
  THREE.PlaneGeometry = function(width, height, widthSegments, heightSegments) {
    THREE.Geometry.call(this);
    this.type = 'PlaneGeometry';
    this.parameters = {
      width: width,
      height: height,
      widthSegments: widthSegments,
      heightSegments: heightSegments
    };
    this.fromBufferGeometry(new THREE.PlaneBufferGeometry(width, height, widthSegments, heightSegments));
  };
  THREE.PlaneGeometry.prototype = Object.create(THREE.Geometry.prototype);
  THREE.PlaneGeometry.prototype.constructor = THREE.PlaneGeometry;
  THREE.PlaneBufferGeometry = function(width, height, widthSegments, heightSegments) {
    THREE.BufferGeometry.call(this);
    this.type = 'PlaneBufferGeometry';
    this.parameters = {
      width: width,
      height: height,
      widthSegments: widthSegments,
      heightSegments: heightSegments
    };
    var width_half = width / 2;
    var height_half = height / 2;
    var gridX = Math.floor(widthSegments) || 1;
    var gridY = Math.floor(heightSegments) || 1;
    var gridX1 = gridX + 1;
    var gridY1 = gridY + 1;
    var segment_width = width / gridX;
    var segment_height = height / gridY;
    var vertices = new Float32Array(gridX1 * gridY1 * 3);
    var normals = new Float32Array(gridX1 * gridY1 * 3);
    var uvs = new Float32Array(gridX1 * gridY1 * 2);
    var offset = 0;
    var offset2 = 0;
    for (var iy = 0; iy < gridY1; iy++) {
      var y = iy * segment_height - height_half;
      for (var ix = 0; ix < gridX1; ix++) {
        var x = ix * segment_width - width_half;
        vertices[offset] = x;
        vertices[offset + 1] = -y;
        normals[offset + 2] = 1;
        uvs[offset2] = ix / gridX;
        uvs[offset2 + 1] = 1 - (iy / gridY);
        offset += 3;
        offset2 += 2;
      }
    }
    offset = 0;
    var indices = new ((vertices.length / 3) > 65535 ? Uint32Array : Uint16Array)(gridX * gridY * 6);
    for (var iy = 0; iy < gridY; iy++) {
      for (var ix = 0; ix < gridX; ix++) {
        var a = ix + gridX1 * iy;
        var b = ix + gridX1 * (iy + 1);
        var c = (ix + 1) + gridX1 * (iy + 1);
        var d = (ix + 1) + gridX1 * iy;
        indices[offset] = a;
        indices[offset + 1] = b;
        indices[offset + 2] = d;
        indices[offset + 3] = b;
        indices[offset + 4] = c;
        indices[offset + 5] = d;
        offset += 6;
      }
    }
    this.setIndex(new THREE.BufferAttribute(indices, 1));
    this.addAttribute('position', new THREE.BufferAttribute(vertices, 3));
    this.addAttribute('normal', new THREE.BufferAttribute(normals, 3));
    this.addAttribute('uv', new THREE.BufferAttribute(uvs, 2));
  };
  THREE.PlaneBufferGeometry.prototype = Object.create(THREE.BufferGeometry.prototype);
  THREE.PlaneBufferGeometry.prototype.constructor = THREE.PlaneBufferGeometry;
  THREE.RingBufferGeometry = function(innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength) {
    THREE.BufferGeometry.call(this);
    this.type = 'RingBufferGeometry';
    this.parameters = {
      innerRadius: innerRadius,
      outerRadius: outerRadius,
      thetaSegments: thetaSegments,
      phiSegments: phiSegments,
      thetaStart: thetaStart,
      thetaLength: thetaLength
    };
    innerRadius = innerRadius || 20;
    outerRadius = outerRadius || 50;
    thetaStart = thetaStart !== undefined ? thetaStart : 0;
    thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2;
    thetaSegments = thetaSegments !== undefined ? Math.max(3, thetaSegments) : 8;
    phiSegments = phiSegments !== undefined ? Math.max(1, phiSegments) : 1;
    var vertexCount = (thetaSegments + 1) * (phiSegments + 1);
    var indexCount = thetaSegments * phiSegments * 2 * 3;
    var indices = new THREE.BufferAttribute(new (indexCount > 65535 ? Uint32Array : Uint16Array)(indexCount), 1);
    var vertices = new THREE.BufferAttribute(new Float32Array(vertexCount * 3), 3);
    var normals = new THREE.BufferAttribute(new Float32Array(vertexCount * 3), 3);
    var uvs = new THREE.BufferAttribute(new Float32Array(vertexCount * 2), 2);
    var index = 0,
        indexOffset = 0,
        segment;
    var radius = innerRadius;
    var radiusStep = ((outerRadius - innerRadius) / phiSegments);
    var vertex = new THREE.Vector3();
    var uv = new THREE.Vector2();
    var j,
        i;
    for (j = 0; j <= phiSegments; j++) {
      for (i = 0; i <= thetaSegments; i++) {
        segment = thetaStart + i / thetaSegments * thetaLength;
        vertex.x = radius * Math.cos(segment);
        vertex.y = radius * Math.sin(segment);
        vertices.setXYZ(index, vertex.x, vertex.y, vertex.z);
        normals.setXYZ(index, 0, 0, 1);
        uv.x = (vertex.x / outerRadius + 1) / 2;
        uv.y = (vertex.y / outerRadius + 1) / 2;
        uvs.setXY(index, uv.x, uv.y);
        index++;
      }
      radius += radiusStep;
    }
    for (j = 0; j < phiSegments; j++) {
      var thetaSegmentLevel = j * (thetaSegments + 1);
      for (i = 0; i < thetaSegments; i++) {
        segment = i + thetaSegmentLevel;
        var a = segment;
        var b = segment + thetaSegments + 1;
        var c = segment + thetaSegments + 2;
        var d = segment + 1;
        indices.setX(indexOffset, a);
        indexOffset++;
        indices.setX(indexOffset, b);
        indexOffset++;
        indices.setX(indexOffset, c);
        indexOffset++;
        indices.setX(indexOffset, a);
        indexOffset++;
        indices.setX(indexOffset, c);
        indexOffset++;
        indices.setX(indexOffset, d);
        indexOffset++;
      }
    }
    this.setIndex(indices);
    this.addAttribute('position', vertices);
    this.addAttribute('normal', normals);
    this.addAttribute('uv', uvs);
  };
  THREE.RingBufferGeometry.prototype = Object.create(THREE.BufferGeometry.prototype);
  THREE.RingBufferGeometry.prototype.constructor = THREE.RingBufferGeometry;
  THREE.RingGeometry = function(innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength) {
    THREE.Geometry.call(this);
    this.type = 'RingGeometry';
    this.parameters = {
      innerRadius: innerRadius,
      outerRadius: outerRadius,
      thetaSegments: thetaSegments,
      phiSegments: phiSegments,
      thetaStart: thetaStart,
      thetaLength: thetaLength
    };
    this.fromBufferGeometry(new THREE.RingBufferGeometry(innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength));
  };
  THREE.RingGeometry.prototype = Object.create(THREE.Geometry.prototype);
  THREE.RingGeometry.prototype.constructor = THREE.RingGeometry;
  THREE.SphereGeometry = function(radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength) {
    THREE.Geometry.call(this);
    this.type = 'SphereGeometry';
    this.parameters = {
      radius: radius,
      widthSegments: widthSegments,
      heightSegments: heightSegments,
      phiStart: phiStart,
      phiLength: phiLength,
      thetaStart: thetaStart,
      thetaLength: thetaLength
    };
    this.fromBufferGeometry(new THREE.SphereBufferGeometry(radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength));
  };
  THREE.SphereGeometry.prototype = Object.create(THREE.Geometry.prototype);
  THREE.SphereGeometry.prototype.constructor = THREE.SphereGeometry;
  THREE.SphereBufferGeometry = function(radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength) {
    THREE.BufferGeometry.call(this);
    this.type = 'SphereBufferGeometry';
    this.parameters = {
      radius: radius,
      widthSegments: widthSegments,
      heightSegments: heightSegments,
      phiStart: phiStart,
      phiLength: phiLength,
      thetaStart: thetaStart,
      thetaLength: thetaLength
    };
    radius = radius || 50;
    widthSegments = Math.max(3, Math.floor(widthSegments) || 8);
    heightSegments = Math.max(2, Math.floor(heightSegments) || 6);
    phiStart = phiStart !== undefined ? phiStart : 0;
    phiLength = phiLength !== undefined ? phiLength : Math.PI * 2;
    thetaStart = thetaStart !== undefined ? thetaStart : 0;
    thetaLength = thetaLength !== undefined ? thetaLength : Math.PI;
    var thetaEnd = thetaStart + thetaLength;
    var vertexCount = ((widthSegments + 1) * (heightSegments + 1));
    var positions = new THREE.BufferAttribute(new Float32Array(vertexCount * 3), 3);
    var normals = new THREE.BufferAttribute(new Float32Array(vertexCount * 3), 3);
    var uvs = new THREE.BufferAttribute(new Float32Array(vertexCount * 2), 2);
    var index = 0,
        vertices = [],
        normal = new THREE.Vector3();
    for (var y = 0; y <= heightSegments; y++) {
      var verticesRow = [];
      var v = y / heightSegments;
      for (var x = 0; x <= widthSegments; x++) {
        var u = x / widthSegments;
        var px = -radius * Math.cos(phiStart + u * phiLength) * Math.sin(thetaStart + v * thetaLength);
        var py = radius * Math.cos(thetaStart + v * thetaLength);
        var pz = radius * Math.sin(phiStart + u * phiLength) * Math.sin(thetaStart + v * thetaLength);
        normal.set(px, py, pz).normalize();
        positions.setXYZ(index, px, py, pz);
        normals.setXYZ(index, normal.x, normal.y, normal.z);
        uvs.setXY(index, u, 1 - v);
        verticesRow.push(index);
        index++;
      }
      vertices.push(verticesRow);
    }
    var indices = [];
    for (var y = 0; y < heightSegments; y++) {
      for (var x = 0; x < widthSegments; x++) {
        var v1 = vertices[y][x + 1];
        var v2 = vertices[y][x];
        var v3 = vertices[y + 1][x];
        var v4 = vertices[y + 1][x + 1];
        if (y !== 0 || thetaStart > 0)
          indices.push(v1, v2, v4);
        if (y !== heightSegments - 1 || thetaEnd < Math.PI)
          indices.push(v2, v3, v4);
      }
    }
    this.setIndex(new (positions.count > 65535 ? THREE.Uint32Attribute : THREE.Uint16Attribute)(indices, 1));
    this.addAttribute('position', positions);
    this.addAttribute('normal', normals);
    this.addAttribute('uv', uvs);
    this.boundingSphere = new THREE.Sphere(new THREE.Vector3(), radius);
  };
  THREE.SphereBufferGeometry.prototype = Object.create(THREE.BufferGeometry.prototype);
  THREE.SphereBufferGeometry.prototype.constructor = THREE.SphereBufferGeometry;
  THREE.TextGeometry = function(text, parameters) {
    parameters = parameters || {};
    var font = parameters.font;
    if (font instanceof THREE.Font === false) {
      console.error('THREE.TextGeometry: font parameter is not an instance of THREE.Font.');
      return new THREE.Geometry();
    }
    var shapes = font.generateShapes(text, parameters.size, parameters.curveSegments);
    parameters.amount = parameters.height !== undefined ? parameters.height : 50;
    if (parameters.bevelThickness === undefined)
      parameters.bevelThickness = 10;
    if (parameters.bevelSize === undefined)
      parameters.bevelSize = 8;
    if (parameters.bevelEnabled === undefined)
      parameters.bevelEnabled = false;
    THREE.ExtrudeGeometry.call(this, shapes, parameters);
    this.type = 'TextGeometry';
  };
  THREE.TextGeometry.prototype = Object.create(THREE.ExtrudeGeometry.prototype);
  THREE.TextGeometry.prototype.constructor = THREE.TextGeometry;
  THREE.TorusBufferGeometry = function(radius, tube, radialSegments, tubularSegments, arc) {
    THREE.BufferGeometry.call(this);
    this.type = 'TorusBufferGeometry';
    this.parameters = {
      radius: radius,
      tube: tube,
      radialSegments: radialSegments,
      tubularSegments: tubularSegments,
      arc: arc
    };
    radius = radius || 100;
    tube = tube || 40;
    radialSegments = Math.floor(radialSegments) || 8;
    tubularSegments = Math.floor(tubularSegments) || 6;
    arc = arc || Math.PI * 2;
    var vertexCount = ((radialSegments + 1) * (tubularSegments + 1));
    var indexCount = radialSegments * tubularSegments * 2 * 3;
    var indices = new (indexCount > 65535 ? Uint32Array : Uint16Array)(indexCount);
    var vertices = new Float32Array(vertexCount * 3);
    var normals = new Float32Array(vertexCount * 3);
    var uvs = new Float32Array(vertexCount * 2);
    var vertexBufferOffset = 0;
    var uvBufferOffset = 0;
    var indexBufferOffset = 0;
    var center = new THREE.Vector3();
    var vertex = new THREE.Vector3();
    var normal = new THREE.Vector3();
    var j,
        i;
    for (j = 0; j <= radialSegments; j++) {
      for (i = 0; i <= tubularSegments; i++) {
        var u = i / tubularSegments * arc;
        var v = j / radialSegments * Math.PI * 2;
        vertex.x = (radius + tube * Math.cos(v)) * Math.cos(u);
        vertex.y = (radius + tube * Math.cos(v)) * Math.sin(u);
        vertex.z = tube * Math.sin(v);
        vertices[vertexBufferOffset] = vertex.x;
        vertices[vertexBufferOffset + 1] = vertex.y;
        vertices[vertexBufferOffset + 2] = vertex.z;
        center.x = radius * Math.cos(u);
        center.y = radius * Math.sin(u);
        normal.subVectors(vertex, center).normalize();
        normals[vertexBufferOffset] = normal.x;
        normals[vertexBufferOffset + 1] = normal.y;
        normals[vertexBufferOffset + 2] = normal.z;
        uvs[uvBufferOffset] = i / tubularSegments;
        uvs[uvBufferOffset + 1] = j / radialSegments;
        vertexBufferOffset += 3;
        uvBufferOffset += 2;
      }
    }
    for (j = 1; j <= radialSegments; j++) {
      for (i = 1; i <= tubularSegments; i++) {
        var a = (tubularSegments + 1) * j + i - 1;
        var b = (tubularSegments + 1) * (j - 1) + i - 1;
        var c = (tubularSegments + 1) * (j - 1) + i;
        var d = (tubularSegments + 1) * j + i;
        indices[indexBufferOffset] = a;
        indices[indexBufferOffset + 1] = b;
        indices[indexBufferOffset + 2] = d;
        indices[indexBufferOffset + 3] = b;
        indices[indexBufferOffset + 4] = c;
        indices[indexBufferOffset + 5] = d;
        indexBufferOffset += 6;
      }
    }
    this.setIndex(new THREE.BufferAttribute(indices, 1));
    this.addAttribute('position', new THREE.BufferAttribute(vertices, 3));
    this.addAttribute('normal', new THREE.BufferAttribute(normals, 3));
    this.addAttribute('uv', new THREE.BufferAttribute(uvs, 2));
  };
  THREE.TorusBufferGeometry.prototype = Object.create(THREE.BufferGeometry.prototype);
  THREE.TorusBufferGeometry.prototype.constructor = THREE.TorusBufferGeometry;
  THREE.TorusGeometry = function(radius, tube, radialSegments, tubularSegments, arc) {
    THREE.Geometry.call(this);
    this.type = 'TorusGeometry';
    this.parameters = {
      radius: radius,
      tube: tube,
      radialSegments: radialSegments,
      tubularSegments: tubularSegments,
      arc: arc
    };
    this.fromBufferGeometry(new THREE.TorusBufferGeometry(radius, tube, radialSegments, tubularSegments, arc));
  };
  THREE.TorusGeometry.prototype = Object.create(THREE.Geometry.prototype);
  THREE.TorusGeometry.prototype.constructor = THREE.TorusGeometry;
  THREE.TorusKnotBufferGeometry = function(radius, tube, tubularSegments, radialSegments, p, q) {
    THREE.BufferGeometry.call(this);
    this.type = 'TorusKnotBufferGeometry';
    this.parameters = {
      radius: radius,
      tube: tube,
      tubularSegments: tubularSegments,
      radialSegments: radialSegments,
      p: p,
      q: q
    };
    radius = radius || 100;
    tube = tube || 40;
    tubularSegments = Math.floor(tubularSegments) || 64;
    radialSegments = Math.floor(radialSegments) || 8;
    p = p || 2;
    q = q || 3;
    var vertexCount = ((radialSegments + 1) * (tubularSegments + 1));
    var indexCount = radialSegments * tubularSegments * 2 * 3;
    var indices = new THREE.BufferAttribute(new (indexCount > 65535 ? Uint32Array : Uint16Array)(indexCount), 1);
    var vertices = new THREE.BufferAttribute(new Float32Array(vertexCount * 3), 3);
    var normals = new THREE.BufferAttribute(new Float32Array(vertexCount * 3), 3);
    var uvs = new THREE.BufferAttribute(new Float32Array(vertexCount * 2), 2);
    var i,
        j,
        index = 0,
        indexOffset = 0;
    var vertex = new THREE.Vector3();
    var normal = new THREE.Vector3();
    var uv = new THREE.Vector2();
    var P1 = new THREE.Vector3();
    var P2 = new THREE.Vector3();
    var B = new THREE.Vector3();
    var T = new THREE.Vector3();
    var N = new THREE.Vector3();
    for (i = 0; i <= tubularSegments; ++i) {
      var u = i / tubularSegments * p * Math.PI * 2;
      calculatePositionOnCurve(u, p, q, radius, P1);
      calculatePositionOnCurve(u + 0.01, p, q, radius, P2);
      T.subVectors(P2, P1);
      N.addVectors(P2, P1);
      B.crossVectors(T, N);
      N.crossVectors(B, T);
      B.normalize();
      N.normalize();
      for (j = 0; j <= radialSegments; ++j) {
        var v = j / radialSegments * Math.PI * 2;
        var cx = -tube * Math.cos(v);
        var cy = tube * Math.sin(v);
        vertex.x = P1.x + (cx * N.x + cy * B.x);
        vertex.y = P1.y + (cx * N.y + cy * B.y);
        vertex.z = P1.z + (cx * N.z + cy * B.z);
        vertices.setXYZ(index, vertex.x, vertex.y, vertex.z);
        normal.subVectors(vertex, P1).normalize();
        normals.setXYZ(index, normal.x, normal.y, normal.z);
        uv.x = i / tubularSegments;
        uv.y = j / radialSegments;
        uvs.setXY(index, uv.x, uv.y);
        index++;
      }
    }
    for (j = 1; j <= tubularSegments; j++) {
      for (i = 1; i <= radialSegments; i++) {
        var a = (radialSegments + 1) * (j - 1) + (i - 1);
        var b = (radialSegments + 1) * j + (i - 1);
        var c = (radialSegments + 1) * j + i;
        var d = (radialSegments + 1) * (j - 1) + i;
        indices.setX(indexOffset, a);
        indexOffset++;
        indices.setX(indexOffset, b);
        indexOffset++;
        indices.setX(indexOffset, d);
        indexOffset++;
        indices.setX(indexOffset, b);
        indexOffset++;
        indices.setX(indexOffset, c);
        indexOffset++;
        indices.setX(indexOffset, d);
        indexOffset++;
      }
    }
    this.setIndex(indices);
    this.addAttribute('position', vertices);
    this.addAttribute('normal', normals);
    this.addAttribute('uv', uvs);
    function calculatePositionOnCurve(u, p, q, radius, position) {
      var cu = Math.cos(u);
      var su = Math.sin(u);
      var quOverP = q / p * u;
      var cs = Math.cos(quOverP);
      position.x = radius * (2 + cs) * 0.5 * cu;
      position.y = radius * (2 + cs) * su * 0.5;
      position.z = radius * Math.sin(quOverP) * 0.5;
    }
  };
  THREE.TorusKnotBufferGeometry.prototype = Object.create(THREE.BufferGeometry.prototype);
  THREE.TorusKnotBufferGeometry.prototype.constructor = THREE.TorusKnotBufferGeometry;
  THREE.TorusKnotGeometry = function(radius, tube, tubularSegments, radialSegments, p, q, heightScale) {
    THREE.Geometry.call(this);
    this.type = 'TorusKnotGeometry';
    this.parameters = {
      radius: radius,
      tube: tube,
      tubularSegments: tubularSegments,
      radialSegments: radialSegments,
      p: p,
      q: q
    };
    if (heightScale !== undefined)
      console.warn('THREE.TorusKnotGeometry: heightScale has been deprecated. Use .scale( x, y, z ) instead.');
    this.fromBufferGeometry(new THREE.TorusKnotBufferGeometry(radius, tube, tubularSegments, radialSegments, p, q));
    this.mergeVertices();
  };
  THREE.TorusKnotGeometry.prototype = Object.create(THREE.Geometry.prototype);
  THREE.TorusKnotGeometry.prototype.constructor = THREE.TorusKnotGeometry;
  THREE.TubeGeometry = function(path, segments, radius, radialSegments, closed, taper) {
    THREE.Geometry.call(this);
    this.type = 'TubeGeometry';
    this.parameters = {
      path: path,
      segments: segments,
      radius: radius,
      radialSegments: radialSegments,
      closed: closed,
      taper: taper
    };
    segments = segments || 64;
    radius = radius || 1;
    radialSegments = radialSegments || 8;
    closed = closed || false;
    taper = taper || THREE.TubeGeometry.NoTaper;
    var grid = [];
    var scope = this,
        tangent,
        normal,
        binormal,
        numpoints = segments + 1,
        u,
        v,
        r,
        cx,
        cy,
        pos,
        pos2 = new THREE.Vector3(),
        i,
        j,
        ip,
        jp,
        a,
        b,
        c,
        d,
        uva,
        uvb,
        uvc,
        uvd;
    var frames = new THREE.TubeGeometry.FrenetFrames(path, segments, closed),
        tangents = frames.tangents,
        normals = frames.normals,
        binormals = frames.binormals;
    this.tangents = tangents;
    this.normals = normals;
    this.binormals = binormals;
    function vert(x, y, z) {
      return scope.vertices.push(new THREE.Vector3(x, y, z)) - 1;
    }
    for (i = 0; i < numpoints; i++) {
      grid[i] = [];
      u = i / (numpoints - 1);
      pos = path.getPointAt(u);
      tangent = tangents[i];
      normal = normals[i];
      binormal = binormals[i];
      r = radius * taper(u);
      for (j = 0; j < radialSegments; j++) {
        v = j / radialSegments * 2 * Math.PI;
        cx = -r * Math.cos(v);
        cy = r * Math.sin(v);
        pos2.copy(pos);
        pos2.x += cx * normal.x + cy * binormal.x;
        pos2.y += cx * normal.y + cy * binormal.y;
        pos2.z += cx * normal.z + cy * binormal.z;
        grid[i][j] = vert(pos2.x, pos2.y, pos2.z);
      }
    }
    for (i = 0; i < segments; i++) {
      for (j = 0; j < radialSegments; j++) {
        ip = (closed) ? (i + 1) % segments : i + 1;
        jp = (j + 1) % radialSegments;
        a = grid[i][j];
        b = grid[ip][j];
        c = grid[ip][jp];
        d = grid[i][jp];
        uva = new THREE.Vector2(i / segments, j / radialSegments);
        uvb = new THREE.Vector2((i + 1) / segments, j / radialSegments);
        uvc = new THREE.Vector2((i + 1) / segments, (j + 1) / radialSegments);
        uvd = new THREE.Vector2(i / segments, (j + 1) / radialSegments);
        this.faces.push(new THREE.Face3(a, b, d));
        this.faceVertexUvs[0].push([uva, uvb, uvd]);
        this.faces.push(new THREE.Face3(b, c, d));
        this.faceVertexUvs[0].push([uvb.clone(), uvc, uvd.clone()]);
      }
    }
    this.computeFaceNormals();
    this.computeVertexNormals();
  };
  THREE.TubeGeometry.prototype = Object.create(THREE.Geometry.prototype);
  THREE.TubeGeometry.prototype.constructor = THREE.TubeGeometry;
  THREE.TubeGeometry.NoTaper = function(u) {
    return 1;
  };
  THREE.TubeGeometry.SinusoidalTaper = function(u) {
    return Math.sin(Math.PI * u);
  };
  THREE.TubeGeometry.FrenetFrames = function(path, segments, closed) {
    var normal = new THREE.Vector3(),
        tangents = [],
        normals = [],
        binormals = [],
        vec = new THREE.Vector3(),
        mat = new THREE.Matrix4(),
        numpoints = segments + 1,
        theta,
        smallest,
        tx,
        ty,
        tz,
        i,
        u;
    this.tangents = tangents;
    this.normals = normals;
    this.binormals = binormals;
    for (i = 0; i < numpoints; i++) {
      u = i / (numpoints - 1);
      tangents[i] = path.getTangentAt(u);
      tangents[i].normalize();
    }
    initialNormal3();
    function initialNormal3() {
      normals[0] = new THREE.Vector3();
      binormals[0] = new THREE.Vector3();
      smallest = Number.MAX_VALUE;
      tx = Math.abs(tangents[0].x);
      ty = Math.abs(tangents[0].y);
      tz = Math.abs(tangents[0].z);
      if (tx <= smallest) {
        smallest = tx;
        normal.set(1, 0, 0);
      }
      if (ty <= smallest) {
        smallest = ty;
        normal.set(0, 1, 0);
      }
      if (tz <= smallest) {
        normal.set(0, 0, 1);
      }
      vec.crossVectors(tangents[0], normal).normalize();
      normals[0].crossVectors(tangents[0], vec);
      binormals[0].crossVectors(tangents[0], normals[0]);
    }
    for (i = 1; i < numpoints; i++) {
      normals[i] = normals[i - 1].clone();
      binormals[i] = binormals[i - 1].clone();
      vec.crossVectors(tangents[i - 1], tangents[i]);
      if (vec.length() > Number.EPSILON) {
        vec.normalize();
        theta = Math.acos(THREE.Math.clamp(tangents[i - 1].dot(tangents[i]), -1, 1));
        normals[i].applyMatrix4(mat.makeRotationAxis(vec, theta));
      }
      binormals[i].crossVectors(tangents[i], normals[i]);
    }
    if (closed) {
      theta = Math.acos(THREE.Math.clamp(normals[0].dot(normals[numpoints - 1]), -1, 1));
      theta /= (numpoints - 1);
      if (tangents[0].dot(vec.crossVectors(normals[0], normals[numpoints - 1])) > 0) {
        theta = -theta;
      }
      for (i = 1; i < numpoints; i++) {
        normals[i].applyMatrix4(mat.makeRotationAxis(tangents[i], theta * i));
        binormals[i].crossVectors(tangents[i], normals[i]);
      }
    }
  };
  THREE.PolyhedronGeometry = function(vertices, indices, radius, detail) {
    THREE.Geometry.call(this);
    this.type = 'PolyhedronGeometry';
    this.parameters = {
      vertices: vertices,
      indices: indices,
      radius: radius,
      detail: detail
    };
    radius = radius || 1;
    detail = detail || 0;
    var that = this;
    for (var i = 0,
        l = vertices.length; i < l; i += 3) {
      prepare(new THREE.Vector3(vertices[i], vertices[i + 1], vertices[i + 2]));
    }
    var p = this.vertices;
    var faces = [];
    for (var i = 0,
        j = 0,
        l = indices.length; i < l; i += 3, j++) {
      var v1 = p[indices[i]];
      var v2 = p[indices[i + 1]];
      var v3 = p[indices[i + 2]];
      faces[j] = new THREE.Face3(v1.index, v2.index, v3.index, [v1.clone(), v2.clone(), v3.clone()]);
    }
    var centroid = new THREE.Vector3();
    for (var i = 0,
        l = faces.length; i < l; i++) {
      subdivide(faces[i], detail);
    }
    for (var i = 0,
        l = this.faceVertexUvs[0].length; i < l; i++) {
      var uvs = this.faceVertexUvs[0][i];
      var x0 = uvs[0].x;
      var x1 = uvs[1].x;
      var x2 = uvs[2].x;
      var max = Math.max(x0, x1, x2);
      var min = Math.min(x0, x1, x2);
      if (max > 0.9 && min < 0.1) {
        if (x0 < 0.2)
          uvs[0].x += 1;
        if (x1 < 0.2)
          uvs[1].x += 1;
        if (x2 < 0.2)
          uvs[2].x += 1;
      }
    }
    for (var i = 0,
        l = this.vertices.length; i < l; i++) {
      this.vertices[i].multiplyScalar(radius);
    }
    this.mergeVertices();
    this.computeFaceNormals();
    this.boundingSphere = new THREE.Sphere(new THREE.Vector3(), radius);
    function prepare(vector) {
      var vertex = vector.normalize().clone();
      vertex.index = that.vertices.push(vertex) - 1;
      var u = azimuth(vector) / 2 / Math.PI + 0.5;
      var v = inclination(vector) / Math.PI + 0.5;
      vertex.uv = new THREE.Vector2(u, 1 - v);
      return vertex;
    }
    function make(v1, v2, v3) {
      var face = new THREE.Face3(v1.index, v2.index, v3.index, [v1.clone(), v2.clone(), v3.clone()]);
      that.faces.push(face);
      centroid.copy(v1).add(v2).add(v3).divideScalar(3);
      var azi = azimuth(centroid);
      that.faceVertexUvs[0].push([correctUV(v1.uv, v1, azi), correctUV(v2.uv, v2, azi), correctUV(v3.uv, v3, azi)]);
    }
    function subdivide(face, detail) {
      var cols = Math.pow(2, detail);
      var a = prepare(that.vertices[face.a]);
      var b = prepare(that.vertices[face.b]);
      var c = prepare(that.vertices[face.c]);
      var v = [];
      for (var i = 0; i <= cols; i++) {
        v[i] = [];
        var aj = prepare(a.clone().lerp(c, i / cols));
        var bj = prepare(b.clone().lerp(c, i / cols));
        var rows = cols - i;
        for (var j = 0; j <= rows; j++) {
          if (j === 0 && i === cols) {
            v[i][j] = aj;
          } else {
            v[i][j] = prepare(aj.clone().lerp(bj, j / rows));
          }
        }
      }
      for (var i = 0; i < cols; i++) {
        for (var j = 0; j < 2 * (cols - i) - 1; j++) {
          var k = Math.floor(j / 2);
          if (j % 2 === 0) {
            make(v[i][k + 1], v[i + 1][k], v[i][k]);
          } else {
            make(v[i][k + 1], v[i + 1][k + 1], v[i + 1][k]);
          }
        }
      }
    }
    function azimuth(vector) {
      return Math.atan2(vector.z, -vector.x);
    }
    function inclination(vector) {
      return Math.atan2(-vector.y, Math.sqrt((vector.x * vector.x) + (vector.z * vector.z)));
    }
    function correctUV(uv, vector, azimuth) {
      if ((azimuth < 0) && (uv.x === 1))
        uv = new THREE.Vector2(uv.x - 1, uv.y);
      if ((vector.x === 0) && (vector.z === 0))
        uv = new THREE.Vector2(azimuth / 2 / Math.PI + 0.5, uv.y);
      return uv.clone();
    }
  };
  THREE.PolyhedronGeometry.prototype = Object.create(THREE.Geometry.prototype);
  THREE.PolyhedronGeometry.prototype.constructor = THREE.PolyhedronGeometry;
  THREE.DodecahedronGeometry = function(radius, detail) {
    var t = (1 + Math.sqrt(5)) / 2;
    var r = 1 / t;
    var vertices = [-1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 0, -r, -t, 0, -r, t, 0, r, -t, 0, r, t, -r, -t, 0, -r, t, 0, r, -t, 0, r, t, 0, -t, 0, -r, t, 0, -r, -t, 0, r, t, 0, r];
    var indices = [3, 11, 7, 3, 7, 15, 3, 15, 13, 7, 19, 17, 7, 17, 6, 7, 6, 15, 17, 4, 8, 17, 8, 10, 17, 10, 6, 8, 0, 16, 8, 16, 2, 8, 2, 10, 0, 12, 1, 0, 1, 18, 0, 18, 16, 6, 10, 2, 6, 2, 13, 6, 13, 15, 2, 16, 18, 2, 18, 3, 2, 3, 13, 18, 1, 9, 18, 9, 11, 18, 11, 3, 4, 14, 12, 4, 12, 0, 4, 0, 8, 11, 9, 5, 11, 5, 19, 11, 19, 7, 19, 5, 14, 19, 14, 4, 19, 4, 17, 1, 12, 14, 1, 14, 5, 1, 5, 9];
    THREE.PolyhedronGeometry.call(this, vertices, indices, radius, detail);
    this.type = 'DodecahedronGeometry';
    this.parameters = {
      radius: radius,
      detail: detail
    };
  };
  THREE.DodecahedronGeometry.prototype = Object.create(THREE.PolyhedronGeometry.prototype);
  THREE.DodecahedronGeometry.prototype.constructor = THREE.DodecahedronGeometry;
  THREE.IcosahedronGeometry = function(radius, detail) {
    var t = (1 + Math.sqrt(5)) / 2;
    var vertices = [-1, t, 0, 1, t, 0, -1, -t, 0, 1, -t, 0, 0, -1, t, 0, 1, t, 0, -1, -t, 0, 1, -t, t, 0, -1, t, 0, 1, -t, 0, -1, -t, 0, 1];
    var indices = [0, 11, 5, 0, 5, 1, 0, 1, 7, 0, 7, 10, 0, 10, 11, 1, 5, 9, 5, 11, 4, 11, 10, 2, 10, 7, 6, 7, 1, 8, 3, 9, 4, 3, 4, 2, 3, 2, 6, 3, 6, 8, 3, 8, 9, 4, 9, 5, 2, 4, 11, 6, 2, 10, 8, 6, 7, 9, 8, 1];
    THREE.PolyhedronGeometry.call(this, vertices, indices, radius, detail);
    this.type = 'IcosahedronGeometry';
    this.parameters = {
      radius: radius,
      detail: detail
    };
  };
  THREE.IcosahedronGeometry.prototype = Object.create(THREE.PolyhedronGeometry.prototype);
  THREE.IcosahedronGeometry.prototype.constructor = THREE.IcosahedronGeometry;
  THREE.OctahedronGeometry = function(radius, detail) {
    var vertices = [1, 0, 0, -1, 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 1, 0, 0, -1];
    var indices = [0, 2, 4, 0, 4, 3, 0, 3, 5, 0, 5, 2, 1, 2, 5, 1, 5, 3, 1, 3, 4, 1, 4, 2];
    THREE.PolyhedronGeometry.call(this, vertices, indices, radius, detail);
    this.type = 'OctahedronGeometry';
    this.parameters = {
      radius: radius,
      detail: detail
    };
  };
  THREE.OctahedronGeometry.prototype = Object.create(THREE.PolyhedronGeometry.prototype);
  THREE.OctahedronGeometry.prototype.constructor = THREE.OctahedronGeometry;
  THREE.TetrahedronGeometry = function(radius, detail) {
    var vertices = [1, 1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1];
    var indices = [2, 1, 0, 0, 3, 2, 1, 3, 0, 2, 3, 1];
    THREE.PolyhedronGeometry.call(this, vertices, indices, radius, detail);
    this.type = 'TetrahedronGeometry';
    this.parameters = {
      radius: radius,
      detail: detail
    };
  };
  THREE.TetrahedronGeometry.prototype = Object.create(THREE.PolyhedronGeometry.prototype);
  THREE.TetrahedronGeometry.prototype.constructor = THREE.TetrahedronGeometry;
  THREE.ParametricGeometry = function(func, slices, stacks) {
    THREE.Geometry.call(this);
    this.type = 'ParametricGeometry';
    this.parameters = {
      func: func,
      slices: slices,
      stacks: stacks
    };
    var verts = this.vertices;
    var faces = this.faces;
    var uvs = this.faceVertexUvs[0];
    var i,
        j,
        p;
    var u,
        v;
    var sliceCount = slices + 1;
    for (i = 0; i <= stacks; i++) {
      v = i / stacks;
      for (j = 0; j <= slices; j++) {
        u = j / slices;
        p = func(u, v);
        verts.push(p);
      }
    }
    var a,
        b,
        c,
        d;
    var uva,
        uvb,
        uvc,
        uvd;
    for (i = 0; i < stacks; i++) {
      for (j = 0; j < slices; j++) {
        a = i * sliceCount + j;
        b = i * sliceCount + j + 1;
        c = (i + 1) * sliceCount + j + 1;
        d = (i + 1) * sliceCount + j;
        uva = new THREE.Vector2(j / slices, i / stacks);
        uvb = new THREE.Vector2((j + 1) / slices, i / stacks);
        uvc = new THREE.Vector2((j + 1) / slices, (i + 1) / stacks);
        uvd = new THREE.Vector2(j / slices, (i + 1) / stacks);
        faces.push(new THREE.Face3(a, b, d));
        uvs.push([uva, uvb, uvd]);
        faces.push(new THREE.Face3(b, c, d));
        uvs.push([uvb.clone(), uvc, uvd.clone()]);
      }
    }
    this.computeFaceNormals();
    this.computeVertexNormals();
  };
  THREE.ParametricGeometry.prototype = Object.create(THREE.Geometry.prototype);
  THREE.ParametricGeometry.prototype.constructor = THREE.ParametricGeometry;
  THREE.WireframeGeometry = function(geometry) {
    THREE.BufferGeometry.call(this);
    var edge = [0, 0],
        hash = {};
    function sortFunction(a, b) {
      return a - b;
    }
    var keys = ['a', 'b', 'c'];
    if (geometry instanceof THREE.Geometry) {
      var vertices = geometry.vertices;
      var faces = geometry.faces;
      var numEdges = 0;
      var edges = new Uint32Array(6 * faces.length);
      for (var i = 0,
          l = faces.length; i < l; i++) {
        var face = faces[i];
        for (var j = 0; j < 3; j++) {
          edge[0] = face[keys[j]];
          edge[1] = face[keys[(j + 1) % 3]];
          edge.sort(sortFunction);
          var key = edge.toString();
          if (hash[key] === undefined) {
            edges[2 * numEdges] = edge[0];
            edges[2 * numEdges + 1] = edge[1];
            hash[key] = true;
            numEdges++;
          }
        }
      }
      var coords = new Float32Array(numEdges * 2 * 3);
      for (var i = 0,
          l = numEdges; i < l; i++) {
        for (var j = 0; j < 2; j++) {
          var vertex = vertices[edges[2 * i + j]];
          var index = 6 * i + 3 * j;
          coords[index + 0] = vertex.x;
          coords[index + 1] = vertex.y;
          coords[index + 2] = vertex.z;
        }
      }
      this.addAttribute('position', new THREE.BufferAttribute(coords, 3));
    } else if (geometry instanceof THREE.BufferGeometry) {
      if (geometry.index !== null) {
        var indices = geometry.index.array;
        var vertices = geometry.attributes.position;
        var groups = geometry.groups;
        var numEdges = 0;
        if (groups.length === 0) {
          geometry.addGroup(0, indices.length);
        }
        var edges = new Uint32Array(2 * indices.length);
        for (var o = 0,
            ol = groups.length; o < ol; ++o) {
          var group = groups[o];
          var start = group.start;
          var count = group.count;
          for (var i = start,
              il = start + count; i < il; i += 3) {
            for (var j = 0; j < 3; j++) {
              edge[0] = indices[i + j];
              edge[1] = indices[i + (j + 1) % 3];
              edge.sort(sortFunction);
              var key = edge.toString();
              if (hash[key] === undefined) {
                edges[2 * numEdges] = edge[0];
                edges[2 * numEdges + 1] = edge[1];
                hash[key] = true;
                numEdges++;
              }
            }
          }
        }
        var coords = new Float32Array(numEdges * 2 * 3);
        for (var i = 0,
            l = numEdges; i < l; i++) {
          for (var j = 0; j < 2; j++) {
            var index = 6 * i + 3 * j;
            var index2 = edges[2 * i + j];
            coords[index + 0] = vertices.getX(index2);
            coords[index + 1] = vertices.getY(index2);
            coords[index + 2] = vertices.getZ(index2);
          }
        }
        this.addAttribute('position', new THREE.BufferAttribute(coords, 3));
      } else {
        var vertices = geometry.attributes.position.array;
        var numEdges = vertices.length / 3;
        var numTris = numEdges / 3;
        var coords = new Float32Array(numEdges * 2 * 3);
        for (var i = 0,
            l = numTris; i < l; i++) {
          for (var j = 0; j < 3; j++) {
            var index = 18 * i + 6 * j;
            var index1 = 9 * i + 3 * j;
            coords[index + 0] = vertices[index1];
            coords[index + 1] = vertices[index1 + 1];
            coords[index + 2] = vertices[index1 + 2];
            var index2 = 9 * i + 3 * ((j + 1) % 3);
            coords[index + 3] = vertices[index2];
            coords[index + 4] = vertices[index2 + 1];
            coords[index + 5] = vertices[index2 + 2];
          }
        }
        this.addAttribute('position', new THREE.BufferAttribute(coords, 3));
      }
    }
  };
  THREE.WireframeGeometry.prototype = Object.create(THREE.BufferGeometry.prototype);
  THREE.WireframeGeometry.prototype.constructor = THREE.WireframeGeometry;
  THREE.AxisHelper = function(size) {
    size = size || 1;
    var vertices = new Float32Array([0, 0, 0, size, 0, 0, 0, 0, 0, 0, size, 0, 0, 0, 0, 0, 0, size]);
    var colors = new Float32Array([1, 0, 0, 1, 0.6, 0, 0, 1, 0, 0.6, 1, 0, 0, 0, 1, 0, 0.6, 1]);
    var geometry = new THREE.BufferGeometry();
    geometry.addAttribute('position', new THREE.BufferAttribute(vertices, 3));
    geometry.addAttribute('color', new THREE.BufferAttribute(colors, 3));
    var material = new THREE.LineBasicMaterial({vertexColors: THREE.VertexColors});
    THREE.LineSegments.call(this, geometry, material);
  };
  THREE.AxisHelper.prototype = Object.create(THREE.LineSegments.prototype);
  THREE.AxisHelper.prototype.constructor = THREE.AxisHelper;
  THREE.ArrowHelper = (function() {
    var lineGeometry = new THREE.BufferGeometry();
    lineGeometry.addAttribute('position', new THREE.Float32Attribute([0, 0, 0, 0, 1, 0], 3));
    var coneGeometry = new THREE.CylinderBufferGeometry(0, 0.5, 1, 5, 1);
    coneGeometry.translate(0, -0.5, 0);
    return function ArrowHelper(dir, origin, length, color, headLength, headWidth) {
      THREE.Object3D.call(this);
      if (color === undefined)
        color = 0xffff00;
      if (length === undefined)
        length = 1;
      if (headLength === undefined)
        headLength = 0.2 * length;
      if (headWidth === undefined)
        headWidth = 0.2 * headLength;
      this.position.copy(origin);
      this.line = new THREE.Line(lineGeometry, new THREE.LineBasicMaterial({color: color}));
      this.line.matrixAutoUpdate = false;
      this.add(this.line);
      this.cone = new THREE.Mesh(coneGeometry, new THREE.MeshBasicMaterial({color: color}));
      this.cone.matrixAutoUpdate = false;
      this.add(this.cone);
      this.setDirection(dir);
      this.setLength(length, headLength, headWidth);
    };
  }());
  THREE.ArrowHelper.prototype = Object.create(THREE.Object3D.prototype);
  THREE.ArrowHelper.prototype.constructor = THREE.ArrowHelper;
  THREE.ArrowHelper.prototype.setDirection = (function() {
    var axis = new THREE.Vector3();
    var radians;
    return function setDirection(dir) {
      if (dir.y > 0.99999) {
        this.quaternion.set(0, 0, 0, 1);
      } else if (dir.y < -0.99999) {
        this.quaternion.set(1, 0, 0, 0);
      } else {
        axis.set(dir.z, 0, -dir.x).normalize();
        radians = Math.acos(dir.y);
        this.quaternion.setFromAxisAngle(axis, radians);
      }
    };
  }());
  THREE.ArrowHelper.prototype.setLength = function(length, headLength, headWidth) {
    if (headLength === undefined)
      headLength = 0.2 * length;
    if (headWidth === undefined)
      headWidth = 0.2 * headLength;
    this.line.scale.set(1, Math.max(0, length - headLength), 1);
    this.line.updateMatrix();
    this.cone.scale.set(headWidth, headLength, headWidth);
    this.cone.position.y = length;
    this.cone.updateMatrix();
  };
  THREE.ArrowHelper.prototype.setColor = function(color) {
    this.line.material.color.copy(color);
    this.cone.material.color.copy(color);
  };
  THREE.BoxHelper = function(object, color) {
    if (color === undefined)
      color = 0xffff00;
    var indices = new Uint16Array([0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7]);
    var positions = new Float32Array(8 * 3);
    var geometry = new THREE.BufferGeometry();
    geometry.setIndex(new THREE.BufferAttribute(indices, 1));
    geometry.addAttribute('position', new THREE.BufferAttribute(positions, 3));
    THREE.LineSegments.call(this, geometry, new THREE.LineBasicMaterial({color: color}));
    if (object !== undefined) {
      this.update(object);
    }
  };
  THREE.BoxHelper.prototype = Object.create(THREE.LineSegments.prototype);
  THREE.BoxHelper.prototype.constructor = THREE.BoxHelper;
  THREE.BoxHelper.prototype.update = (function() {
    var box = new THREE.Box3();
    return function update(object) {
      if (object instanceof THREE.Box3) {
        box.copy(object);
      } else {
        box.setFromObject(object);
      }
      if (box.isEmpty())
        return;
      var min = box.min;
      var max = box.max;
      var position = this.geometry.attributes.position;
      var array = position.array;
      array[0] = max.x;
      array[1] = max.y;
      array[2] = max.z;
      array[3] = min.x;
      array[4] = max.y;
      array[5] = max.z;
      array[6] = min.x;
      array[7] = min.y;
      array[8] = max.z;
      array[9] = max.x;
      array[10] = min.y;
      array[11] = max.z;
      array[12] = max.x;
      array[13] = max.y;
      array[14] = min.z;
      array[15] = min.x;
      array[16] = max.y;
      array[17] = min.z;
      array[18] = min.x;
      array[19] = min.y;
      array[20] = min.z;
      array[21] = max.x;
      array[22] = min.y;
      array[23] = min.z;
      position.needsUpdate = true;
      this.geometry.computeBoundingSphere();
    };
  })();
  THREE.BoundingBoxHelper = function(object, hex) {
    var color = (hex !== undefined) ? hex : 0x888888;
    this.object = object;
    this.box = new THREE.Box3();
    THREE.Mesh.call(this, new THREE.BoxGeometry(1, 1, 1), new THREE.MeshBasicMaterial({
      color: color,
      wireframe: true
    }));
  };
  THREE.BoundingBoxHelper.prototype = Object.create(THREE.Mesh.prototype);
  THREE.BoundingBoxHelper.prototype.constructor = THREE.BoundingBoxHelper;
  THREE.BoundingBoxHelper.prototype.update = function() {
    this.box.setFromObject(this.object);
    this.box.size(this.scale);
    this.box.center(this.position);
  };
  THREE.CameraHelper = function(camera) {
    var geometry = new THREE.Geometry();
    var material = new THREE.LineBasicMaterial({
      color: 0xffffff,
      vertexColors: THREE.FaceColors
    });
    var pointMap = {};
    var hexFrustum = 0xffaa00;
    var hexCone = 0xff0000;
    var hexUp = 0x00aaff;
    var hexTarget = 0xffffff;
    var hexCross = 0x333333;
    addLine("n1", "n2", hexFrustum);
    addLine("n2", "n4", hexFrustum);
    addLine("n4", "n3", hexFrustum);
    addLine("n3", "n1", hexFrustum);
    addLine("f1", "f2", hexFrustum);
    addLine("f2", "f4", hexFrustum);
    addLine("f4", "f3", hexFrustum);
    addLine("f3", "f1", hexFrustum);
    addLine("n1", "f1", hexFrustum);
    addLine("n2", "f2", hexFrustum);
    addLine("n3", "f3", hexFrustum);
    addLine("n4", "f4", hexFrustum);
    addLine("p", "n1", hexCone);
    addLine("p", "n2", hexCone);
    addLine("p", "n3", hexCone);
    addLine("p", "n4", hexCone);
    addLine("u1", "u2", hexUp);
    addLine("u2", "u3", hexUp);
    addLine("u3", "u1", hexUp);
    addLine("c", "t", hexTarget);
    addLine("p", "c", hexCross);
    addLine("cn1", "cn2", hexCross);
    addLine("cn3", "cn4", hexCross);
    addLine("cf1", "cf2", hexCross);
    addLine("cf3", "cf4", hexCross);
    function addLine(a, b, hex) {
      addPoint(a, hex);
      addPoint(b, hex);
    }
    function addPoint(id, hex) {
      geometry.vertices.push(new THREE.Vector3());
      geometry.colors.push(new THREE.Color(hex));
      if (pointMap[id] === undefined) {
        pointMap[id] = [];
      }
      pointMap[id].push(geometry.vertices.length - 1);
    }
    THREE.LineSegments.call(this, geometry, material);
    this.camera = camera;
    if (this.camera.updateProjectionMatrix)
      this.camera.updateProjectionMatrix();
    this.matrix = camera.matrixWorld;
    this.matrixAutoUpdate = false;
    this.pointMap = pointMap;
    this.update();
  };
  THREE.CameraHelper.prototype = Object.create(THREE.LineSegments.prototype);
  THREE.CameraHelper.prototype.constructor = THREE.CameraHelper;
  THREE.CameraHelper.prototype.update = function() {
    var geometry,
        pointMap;
    var vector = new THREE.Vector3();
    var camera = new THREE.Camera();
    function setPoint(point, x, y, z) {
      vector.set(x, y, z).unproject(camera);
      var points = pointMap[point];
      if (points !== undefined) {
        for (var i = 0,
            il = points.length; i < il; i++) {
          geometry.vertices[points[i]].copy(vector);
        }
      }
    }
    return function update() {
      geometry = this.geometry;
      pointMap = this.pointMap;
      var w = 1,
          h = 1;
      camera.projectionMatrix.copy(this.camera.projectionMatrix);
      setPoint("c", 0, 0, -1);
      setPoint("t", 0, 0, 1);
      setPoint("n1", -w, -h, -1);
      setPoint("n2", w, -h, -1);
      setPoint("n3", -w, h, -1);
      setPoint("n4", w, h, -1);
      setPoint("f1", -w, -h, 1);
      setPoint("f2", w, -h, 1);
      setPoint("f3", -w, h, 1);
      setPoint("f4", w, h, 1);
      setPoint("u1", w * 0.7, h * 1.1, -1);
      setPoint("u2", -w * 0.7, h * 1.1, -1);
      setPoint("u3", 0, h * 2, -1);
      setPoint("cf1", -w, 0, 1);
      setPoint("cf2", w, 0, 1);
      setPoint("cf3", 0, -h, 1);
      setPoint("cf4", 0, h, 1);
      setPoint("cn1", -w, 0, -1);
      setPoint("cn2", w, 0, -1);
      setPoint("cn3", 0, -h, -1);
      setPoint("cn4", 0, h, -1);
      geometry.verticesNeedUpdate = true;
    };
  }();
  THREE.DirectionalLightHelper = function(light, size) {
    THREE.Object3D.call(this);
    this.light = light;
    this.light.updateMatrixWorld();
    this.matrix = light.matrixWorld;
    this.matrixAutoUpdate = false;
    if (size === undefined)
      size = 1;
    var geometry = new THREE.BufferGeometry();
    geometry.addAttribute('position', new THREE.Float32Attribute([-size, size, 0, size, size, 0, size, -size, 0, -size, -size, 0, -size, size, 0], 3));
    var material = new THREE.LineBasicMaterial({fog: false});
    this.add(new THREE.Line(geometry, material));
    geometry = new THREE.BufferGeometry();
    geometry.addAttribute('position', new THREE.Float32Attribute([0, 0, 0, 0, 0, 1], 3));
    this.add(new THREE.Line(geometry, material));
    this.update();
  };
  THREE.DirectionalLightHelper.prototype = Object.create(THREE.Object3D.prototype);
  THREE.DirectionalLightHelper.prototype.constructor = THREE.DirectionalLightHelper;
  THREE.DirectionalLightHelper.prototype.dispose = function() {
    var lightPlane = this.children[0];
    var targetLine = this.children[1];
    lightPlane.geometry.dispose();
    lightPlane.material.dispose();
    targetLine.geometry.dispose();
    targetLine.material.dispose();
  };
  THREE.DirectionalLightHelper.prototype.update = function() {
    var v1 = new THREE.Vector3();
    var v2 = new THREE.Vector3();
    var v3 = new THREE.Vector3();
    return function update() {
      v1.setFromMatrixPosition(this.light.matrixWorld);
      v2.setFromMatrixPosition(this.light.target.matrixWorld);
      v3.subVectors(v2, v1);
      var lightPlane = this.children[0];
      var targetLine = this.children[1];
      lightPlane.lookAt(v3);
      lightPlane.material.color.copy(this.light.color).multiplyScalar(this.light.intensity);
      targetLine.lookAt(v3);
      targetLine.scale.z = v3.length();
    };
  }();
  THREE.EdgesHelper = function(object, hex, thresholdAngle) {
    var color = (hex !== undefined) ? hex : 0xffffff;
    THREE.LineSegments.call(this, new THREE.EdgesGeometry(object.geometry, thresholdAngle), new THREE.LineBasicMaterial({color: color}));
    this.matrix = object.matrixWorld;
    this.matrixAutoUpdate = false;
  };
  THREE.EdgesHelper.prototype = Object.create(THREE.LineSegments.prototype);
  THREE.EdgesHelper.prototype.constructor = THREE.EdgesHelper;
  THREE.FaceNormalsHelper = function(object, size, hex, linewidth) {
    this.object = object;
    this.size = (size !== undefined) ? size : 1;
    var color = (hex !== undefined) ? hex : 0xffff00;
    var width = (linewidth !== undefined) ? linewidth : 1;
    var nNormals = 0;
    var objGeometry = this.object.geometry;
    if (objGeometry instanceof THREE.Geometry) {
      nNormals = objGeometry.faces.length;
    } else {
      console.warn('THREE.FaceNormalsHelper: only THREE.Geometry is supported. Use THREE.VertexNormalsHelper, instead.');
    }
    var geometry = new THREE.BufferGeometry();
    var positions = new THREE.Float32Attribute(nNormals * 2 * 3, 3);
    geometry.addAttribute('position', positions);
    THREE.LineSegments.call(this, geometry, new THREE.LineBasicMaterial({
      color: color,
      linewidth: width
    }));
    this.matrixAutoUpdate = false;
    this.update();
  };
  THREE.FaceNormalsHelper.prototype = Object.create(THREE.LineSegments.prototype);
  THREE.FaceNormalsHelper.prototype.constructor = THREE.FaceNormalsHelper;
  THREE.FaceNormalsHelper.prototype.update = (function() {
    var v1 = new THREE.Vector3();
    var v2 = new THREE.Vector3();
    var normalMatrix = new THREE.Matrix3();
    return function update() {
      this.object.updateMatrixWorld(true);
      normalMatrix.getNormalMatrix(this.object.matrixWorld);
      var matrixWorld = this.object.matrixWorld;
      var position = this.geometry.attributes.position;
      var objGeometry = this.object.geometry;
      var vertices = objGeometry.vertices;
      var faces = objGeometry.faces;
      var idx = 0;
      for (var i = 0,
          l = faces.length; i < l; i++) {
        var face = faces[i];
        var normal = face.normal;
        v1.copy(vertices[face.a]).add(vertices[face.b]).add(vertices[face.c]).divideScalar(3).applyMatrix4(matrixWorld);
        v2.copy(normal).applyMatrix3(normalMatrix).normalize().multiplyScalar(this.size).add(v1);
        position.setXYZ(idx, v1.x, v1.y, v1.z);
        idx = idx + 1;
        position.setXYZ(idx, v2.x, v2.y, v2.z);
        idx = idx + 1;
      }
      position.needsUpdate = true;
      return this;
    };
  }());
  THREE.GridHelper = function(size, step, color1, color2) {
    color1 = new THREE.Color(color1 !== undefined ? color1 : 0x444444);
    color2 = new THREE.Color(color2 !== undefined ? color2 : 0x888888);
    var vertices = [];
    var colors = [];
    for (var i = -size,
        j = 0; i <= size; i += step) {
      vertices.push(-size, 0, i, size, 0, i);
      vertices.push(i, 0, -size, i, 0, size);
      var color = i === 0 ? color1 : color2;
      color.toArray(colors, j);
      j += 3;
      color.toArray(colors, j);
      j += 3;
      color.toArray(colors, j);
      j += 3;
      color.toArray(colors, j);
      j += 3;
    }
    var geometry = new THREE.BufferGeometry();
    geometry.addAttribute('position', new THREE.Float32Attribute(vertices, 3));
    geometry.addAttribute('color', new THREE.Float32Attribute(colors, 3));
    var material = new THREE.LineBasicMaterial({vertexColors: THREE.VertexColors});
    THREE.LineSegments.call(this, geometry, material);
  };
  THREE.GridHelper.prototype = Object.create(THREE.LineSegments.prototype);
  THREE.GridHelper.prototype.constructor = THREE.GridHelper;
  THREE.GridHelper.prototype.setColors = function() {
    console.error('THREE.GridHelper: setColors() has been deprecated, pass them in the constructor instead.');
  };
  THREE.HemisphereLightHelper = function(light, sphereSize) {
    THREE.Object3D.call(this);
    this.light = light;
    this.light.updateMatrixWorld();
    this.matrix = light.matrixWorld;
    this.matrixAutoUpdate = false;
    this.colors = [new THREE.Color(), new THREE.Color()];
    var geometry = new THREE.SphereGeometry(sphereSize, 4, 2);
    geometry.rotateX(-Math.PI / 2);
    for (var i = 0,
        il = 8; i < il; i++) {
      geometry.faces[i].color = this.colors[i < 4 ? 0 : 1];
    }
    var material = new THREE.MeshBasicMaterial({
      vertexColors: THREE.FaceColors,
      wireframe: true
    });
    this.lightSphere = new THREE.Mesh(geometry, material);
    this.add(this.lightSphere);
    this.update();
  };
  THREE.HemisphereLightHelper.prototype = Object.create(THREE.Object3D.prototype);
  THREE.HemisphereLightHelper.prototype.constructor = THREE.HemisphereLightHelper;
  THREE.HemisphereLightHelper.prototype.dispose = function() {
    this.lightSphere.geometry.dispose();
    this.lightSphere.material.dispose();
  };
  THREE.HemisphereLightHelper.prototype.update = function() {
    var vector = new THREE.Vector3();
    return function update() {
      this.colors[0].copy(this.light.color).multiplyScalar(this.light.intensity);
      this.colors[1].copy(this.light.groundColor).multiplyScalar(this.light.intensity);
      this.lightSphere.lookAt(vector.setFromMatrixPosition(this.light.matrixWorld).negate());
      this.lightSphere.geometry.colorsNeedUpdate = true;
    };
  }();
  THREE.PointLightHelper = function(light, sphereSize) {
    this.light = light;
    this.light.updateMatrixWorld();
    var geometry = new THREE.SphereBufferGeometry(sphereSize, 4, 2);
    var material = new THREE.MeshBasicMaterial({
      wireframe: true,
      fog: false
    });
    material.color.copy(this.light.color).multiplyScalar(this.light.intensity);
    THREE.Mesh.call(this, geometry, material);
    this.matrix = this.light.matrixWorld;
    this.matrixAutoUpdate = false;
  };
  THREE.PointLightHelper.prototype = Object.create(THREE.Mesh.prototype);
  THREE.PointLightHelper.prototype.constructor = THREE.PointLightHelper;
  THREE.PointLightHelper.prototype.dispose = function() {
    this.geometry.dispose();
    this.material.dispose();
  };
  THREE.PointLightHelper.prototype.update = function() {
    this.material.color.copy(this.light.color).multiplyScalar(this.light.intensity);
  };
  THREE.SkeletonHelper = function(object) {
    this.bones = this.getBoneList(object);
    var geometry = new THREE.Geometry();
    for (var i = 0; i < this.bones.length; i++) {
      var bone = this.bones[i];
      if (bone.parent instanceof THREE.Bone) {
        geometry.vertices.push(new THREE.Vector3());
        geometry.vertices.push(new THREE.Vector3());
        geometry.colors.push(new THREE.Color(0, 0, 1));
        geometry.colors.push(new THREE.Color(0, 1, 0));
      }
    }
    geometry.dynamic = true;
    var material = new THREE.LineBasicMaterial({
      vertexColors: THREE.VertexColors,
      depthTest: false,
      depthWrite: false,
      transparent: true
    });
    THREE.LineSegments.call(this, geometry, material);
    this.root = object;
    this.matrix = object.matrixWorld;
    this.matrixAutoUpdate = false;
    this.update();
  };
  THREE.SkeletonHelper.prototype = Object.create(THREE.LineSegments.prototype);
  THREE.SkeletonHelper.prototype.constructor = THREE.SkeletonHelper;
  THREE.SkeletonHelper.prototype.getBoneList = function(object) {
    var boneList = [];
    if (object instanceof THREE.Bone) {
      boneList.push(object);
    }
    for (var i = 0; i < object.children.length; i++) {
      boneList.push.apply(boneList, this.getBoneList(object.children[i]));
    }
    return boneList;
  };
  THREE.SkeletonHelper.prototype.update = function() {
    var geometry = this.geometry;
    var matrixWorldInv = new THREE.Matrix4().getInverse(this.root.matrixWorld);
    var boneMatrix = new THREE.Matrix4();
    var j = 0;
    for (var i = 0; i < this.bones.length; i++) {
      var bone = this.bones[i];
      if (bone.parent instanceof THREE.Bone) {
        boneMatrix.multiplyMatrices(matrixWorldInv, bone.matrixWorld);
        geometry.vertices[j].setFromMatrixPosition(boneMatrix);
        boneMatrix.multiplyMatrices(matrixWorldInv, bone.parent.matrixWorld);
        geometry.vertices[j + 1].setFromMatrixPosition(boneMatrix);
        j += 2;
      }
    }
    geometry.verticesNeedUpdate = true;
    geometry.computeBoundingSphere();
  };
  THREE.SpotLightHelper = function(light) {
    THREE.Object3D.call(this);
    this.light = light;
    this.light.updateMatrixWorld();
    this.matrix = light.matrixWorld;
    this.matrixAutoUpdate = false;
    var geometry = new THREE.BufferGeometry();
    var positions = [0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, -1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, -1, 1];
    for (var i = 0,
        j = 1,
        l = 32; i < l; i++, j++) {
      var p1 = (i / l) * Math.PI * 2;
      var p2 = (j / l) * Math.PI * 2;
      positions.push(Math.cos(p1), Math.sin(p1), 1, Math.cos(p2), Math.sin(p2), 1);
    }
    geometry.addAttribute('position', new THREE.Float32Attribute(positions, 3));
    var material = new THREE.LineBasicMaterial({fog: false});
    this.cone = new THREE.LineSegments(geometry, material);
    this.add(this.cone);
    this.update();
  };
  THREE.SpotLightHelper.prototype = Object.create(THREE.Object3D.prototype);
  THREE.SpotLightHelper.prototype.constructor = THREE.SpotLightHelper;
  THREE.SpotLightHelper.prototype.dispose = function() {
    this.cone.geometry.dispose();
    this.cone.material.dispose();
  };
  THREE.SpotLightHelper.prototype.update = function() {
    var vector = new THREE.Vector3();
    var vector2 = new THREE.Vector3();
    return function update() {
      var coneLength = this.light.distance ? this.light.distance : 1000;
      var coneWidth = coneLength * Math.tan(this.light.angle);
      this.cone.scale.set(coneWidth, coneWidth, coneLength);
      vector.setFromMatrixPosition(this.light.matrixWorld);
      vector2.setFromMatrixPosition(this.light.target.matrixWorld);
      this.cone.lookAt(vector2.sub(vector));
      this.cone.material.color.copy(this.light.color).multiplyScalar(this.light.intensity);
    };
  }();
  THREE.VertexNormalsHelper = function(object, size, hex, linewidth) {
    this.object = object;
    this.size = (size !== undefined) ? size : 1;
    var color = (hex !== undefined) ? hex : 0xff0000;
    var width = (linewidth !== undefined) ? linewidth : 1;
    var nNormals = 0;
    var objGeometry = this.object.geometry;
    if (objGeometry instanceof THREE.Geometry) {
      nNormals = objGeometry.faces.length * 3;
    } else if (objGeometry instanceof THREE.BufferGeometry) {
      nNormals = objGeometry.attributes.normal.count;
    }
    var geometry = new THREE.BufferGeometry();
    var positions = new THREE.Float32Attribute(nNormals * 2 * 3, 3);
    geometry.addAttribute('position', positions);
    THREE.LineSegments.call(this, geometry, new THREE.LineBasicMaterial({
      color: color,
      linewidth: width
    }));
    this.matrixAutoUpdate = false;
    this.update();
  };
  THREE.VertexNormalsHelper.prototype = Object.create(THREE.LineSegments.prototype);
  THREE.VertexNormalsHelper.prototype.constructor = THREE.VertexNormalsHelper;
  THREE.VertexNormalsHelper.prototype.update = (function() {
    var v1 = new THREE.Vector3();
    var v2 = new THREE.Vector3();
    var normalMatrix = new THREE.Matrix3();
    return function update() {
      var keys = ['a', 'b', 'c'];
      this.object.updateMatrixWorld(true);
      normalMatrix.getNormalMatrix(this.object.matrixWorld);
      var matrixWorld = this.object.matrixWorld;
      var position = this.geometry.attributes.position;
      var objGeometry = this.object.geometry;
      if (objGeometry instanceof THREE.Geometry) {
        var vertices = objGeometry.vertices;
        var faces = objGeometry.faces;
        var idx = 0;
        for (var i = 0,
            l = faces.length; i < l; i++) {
          var face = faces[i];
          for (var j = 0,
              jl = face.vertexNormals.length; j < jl; j++) {
            var vertex = vertices[face[keys[j]]];
            var normal = face.vertexNormals[j];
            v1.copy(vertex).applyMatrix4(matrixWorld);
            v2.copy(normal).applyMatrix3(normalMatrix).normalize().multiplyScalar(this.size).add(v1);
            position.setXYZ(idx, v1.x, v1.y, v1.z);
            idx = idx + 1;
            position.setXYZ(idx, v2.x, v2.y, v2.z);
            idx = idx + 1;
          }
        }
      } else if (objGeometry instanceof THREE.BufferGeometry) {
        var objPos = objGeometry.attributes.position;
        var objNorm = objGeometry.attributes.normal;
        var idx = 0;
        for (var j = 0,
            jl = objPos.count; j < jl; j++) {
          v1.set(objPos.getX(j), objPos.getY(j), objPos.getZ(j)).applyMatrix4(matrixWorld);
          v2.set(objNorm.getX(j), objNorm.getY(j), objNorm.getZ(j));
          v2.applyMatrix3(normalMatrix).normalize().multiplyScalar(this.size).add(v1);
          position.setXYZ(idx, v1.x, v1.y, v1.z);
          idx = idx + 1;
          position.setXYZ(idx, v2.x, v2.y, v2.z);
          idx = idx + 1;
        }
      }
      position.needsUpdate = true;
      return this;
    };
  }());
  THREE.WireframeHelper = function(object, hex) {
    var color = (hex !== undefined) ? hex : 0xffffff;
    THREE.LineSegments.call(this, new THREE.WireframeGeometry(object.geometry), new THREE.LineBasicMaterial({color: color}));
    this.matrix = object.matrixWorld;
    this.matrixAutoUpdate = false;
  };
  THREE.WireframeHelper.prototype = Object.create(THREE.LineSegments.prototype);
  THREE.WireframeHelper.prototype.constructor = THREE.WireframeHelper;
  THREE.ImmediateRenderObject = function(material) {
    THREE.Object3D.call(this);
    this.material = material;
    this.render = function(renderCallback) {};
  };
  THREE.ImmediateRenderObject.prototype = Object.create(THREE.Object3D.prototype);
  THREE.ImmediateRenderObject.prototype.constructor = THREE.ImmediateRenderObject;
  THREE.MorphBlendMesh = function(geometry, material) {
    THREE.Mesh.call(this, geometry, material);
    this.animationsMap = {};
    this.animationsList = [];
    var numFrames = this.geometry.morphTargets.length;
    var name = "__default";
    var startFrame = 0;
    var endFrame = numFrames - 1;
    var fps = numFrames / 1;
    this.createAnimation(name, startFrame, endFrame, fps);
    this.setAnimationWeight(name, 1);
  };
  THREE.MorphBlendMesh.prototype = Object.create(THREE.Mesh.prototype);
  THREE.MorphBlendMesh.prototype.constructor = THREE.MorphBlendMesh;
  THREE.MorphBlendMesh.prototype.createAnimation = function(name, start, end, fps) {
    var animation = {
      start: start,
      end: end,
      length: end - start + 1,
      fps: fps,
      duration: (end - start) / fps,
      lastFrame: 0,
      currentFrame: 0,
      active: false,
      time: 0,
      direction: 1,
      weight: 1,
      directionBackwards: false,
      mirroredLoop: false
    };
    this.animationsMap[name] = animation;
    this.animationsList.push(animation);
  };
  THREE.MorphBlendMesh.prototype.autoCreateAnimations = function(fps) {
    var pattern = /([a-z]+)_?(\d+)/i;
    var firstAnimation,
        frameRanges = {};
    var geometry = this.geometry;
    for (var i = 0,
        il = geometry.morphTargets.length; i < il; i++) {
      var morph = geometry.morphTargets[i];
      var chunks = morph.name.match(pattern);
      if (chunks && chunks.length > 1) {
        var name = chunks[1];
        if (!frameRanges[name])
          frameRanges[name] = {
            start: Infinity,
            end: -Infinity
          };
        var range = frameRanges[name];
        if (i < range.start)
          range.start = i;
        if (i > range.end)
          range.end = i;
        if (!firstAnimation)
          firstAnimation = name;
      }
    }
    for (var name in frameRanges) {
      var range = frameRanges[name];
      this.createAnimation(name, range.start, range.end, fps);
    }
    this.firstAnimation = firstAnimation;
  };
  THREE.MorphBlendMesh.prototype.setAnimationDirectionForward = function(name) {
    var animation = this.animationsMap[name];
    if (animation) {
      animation.direction = 1;
      animation.directionBackwards = false;
    }
  };
  THREE.MorphBlendMesh.prototype.setAnimationDirectionBackward = function(name) {
    var animation = this.animationsMap[name];
    if (animation) {
      animation.direction = -1;
      animation.directionBackwards = true;
    }
  };
  THREE.MorphBlendMesh.prototype.setAnimationFPS = function(name, fps) {
    var animation = this.animationsMap[name];
    if (animation) {
      animation.fps = fps;
      animation.duration = (animation.end - animation.start) / animation.fps;
    }
  };
  THREE.MorphBlendMesh.prototype.setAnimationDuration = function(name, duration) {
    var animation = this.animationsMap[name];
    if (animation) {
      animation.duration = duration;
      animation.fps = (animation.end - animation.start) / animation.duration;
    }
  };
  THREE.MorphBlendMesh.prototype.setAnimationWeight = function(name, weight) {
    var animation = this.animationsMap[name];
    if (animation) {
      animation.weight = weight;
    }
  };
  THREE.MorphBlendMesh.prototype.setAnimationTime = function(name, time) {
    var animation = this.animationsMap[name];
    if (animation) {
      animation.time = time;
    }
  };
  THREE.MorphBlendMesh.prototype.getAnimationTime = function(name) {
    var time = 0;
    var animation = this.animationsMap[name];
    if (animation) {
      time = animation.time;
    }
    return time;
  };
  THREE.MorphBlendMesh.prototype.getAnimationDuration = function(name) {
    var duration = -1;
    var animation = this.animationsMap[name];
    if (animation) {
      duration = animation.duration;
    }
    return duration;
  };
  THREE.MorphBlendMesh.prototype.playAnimation = function(name) {
    var animation = this.animationsMap[name];
    if (animation) {
      animation.time = 0;
      animation.active = true;
    } else {
      console.warn("THREE.MorphBlendMesh: animation[" + name + "] undefined in .playAnimation()");
    }
  };
  THREE.MorphBlendMesh.prototype.stopAnimation = function(name) {
    var animation = this.animationsMap[name];
    if (animation) {
      animation.active = false;
    }
  };
  THREE.MorphBlendMesh.prototype.update = function(delta) {
    for (var i = 0,
        il = this.animationsList.length; i < il; i++) {
      var animation = this.animationsList[i];
      if (!animation.active)
        continue;
      var frameTime = animation.duration / animation.length;
      animation.time += animation.direction * delta;
      if (animation.mirroredLoop) {
        if (animation.time > animation.duration || animation.time < 0) {
          animation.direction *= -1;
          if (animation.time > animation.duration) {
            animation.time = animation.duration;
            animation.directionBackwards = true;
          }
          if (animation.time < 0) {
            animation.time = 0;
            animation.directionBackwards = false;
          }
        }
      } else {
        animation.time = animation.time % animation.duration;
        if (animation.time < 0)
          animation.time += animation.duration;
      }
      var keyframe = animation.start + THREE.Math.clamp(Math.floor(animation.time / frameTime), 0, animation.length - 1);
      var weight = animation.weight;
      if (keyframe !== animation.currentFrame) {
        this.morphTargetInfluences[animation.lastFrame] = 0;
        this.morphTargetInfluences[animation.currentFrame] = 1 * weight;
        this.morphTargetInfluences[keyframe] = 0;
        animation.lastFrame = animation.currentFrame;
        animation.currentFrame = keyframe;
      }
      var mix = (animation.time % frameTime) / frameTime;
      if (animation.directionBackwards)
        mix = 1 - mix;
      if (animation.currentFrame !== animation.lastFrame) {
        this.morphTargetInfluences[animation.currentFrame] = mix * weight;
        this.morphTargetInfluences[animation.lastFrame] = (1 - mix) * weight;
      } else {
        this.morphTargetInfluences[animation.currentFrame] = weight;
      }
    }
  };
  return module.exports;
});

$__System.registerDynamic("29", [], false, function($__require, $__exports, $__module) {
  var _retrieveGlobal = $__System.get("@@global-helpers").prepareGlobal($__module.id, null, null);
  (function() {
    this.j$ = this.jStat = (function(Math, undefined) {
      var concat = Array.prototype.concat;
      var slice = Array.prototype.slice;
      var toString = Object.prototype.toString;
      function calcRdx(n, m) {
        var val = n > m ? n : m;
        return Math.pow(10, 17 - ~~(Math.log(((val > 0) ? val : -val)) * Math.LOG10E));
      }
      var isArray = Array.isArray || function isArray(arg) {
        return toString.call(arg) === '[object Array]';
      };
      function isFunction(arg) {
        return toString.call(arg) === '[object Function]';
      }
      function isNumber(arg) {
        return typeof arg === 'number' && arg === arg;
      }
      function toVector(arr) {
        return concat.apply([], arr);
      }
      function jStat() {
        return new jStat._init(arguments);
      }
      jStat.fn = jStat.prototype;
      jStat._init = function _init(args) {
        var i;
        if (isArray(args[0])) {
          if (isArray(args[0][0])) {
            if (isFunction(args[1]))
              args[0] = jStat.map(args[0], args[1]);
            for (i = 0; i < args[0].length; i++)
              this[i] = args[0][i];
            this.length = args[0].length;
          } else {
            this[0] = isFunction(args[1]) ? jStat.map(args[0], args[1]) : args[0];
            this.length = 1;
          }
        } else if (isNumber(args[0])) {
          this[0] = jStat.seq.apply(null, args);
          this.length = 1;
        } else if (args[0] instanceof jStat) {
          return jStat(args[0].toArray());
        } else {
          this[0] = [];
          this.length = 1;
        }
        return this;
      };
      jStat._init.prototype = jStat.prototype;
      jStat._init.constructor = jStat;
      jStat.utils = {
        calcRdx: calcRdx,
        isArray: isArray,
        isFunction: isFunction,
        isNumber: isNumber,
        toVector: toVector
      };
      jStat.extend = function extend(obj) {
        var i,
            j;
        if (arguments.length === 1) {
          for (j in obj)
            jStat[j] = obj[j];
          return this;
        }
        for (i = 1; i < arguments.length; i++) {
          for (j in arguments[i])
            obj[j] = arguments[i][j];
        }
        return obj;
      };
      jStat.rows = function rows(arr) {
        return arr.length || 1;
      };
      jStat.cols = function cols(arr) {
        return arr[0].length || 1;
      };
      jStat.dimensions = function dimensions(arr) {
        return {
          rows: jStat.rows(arr),
          cols: jStat.cols(arr)
        };
      };
      jStat.row = function row(arr, index) {
        return arr[index];
      };
      jStat.col = function cols(arr, index) {
        var column = new Array(arr.length);
        for (var i = 0; i < arr.length; i++)
          column[i] = [arr[i][index]];
        return column;
      };
      jStat.diag = function diag(arr) {
        var nrow = jStat.rows(arr);
        var res = new Array(nrow);
        for (var row = 0; row < nrow; row++)
          res[row] = [arr[row][row]];
        return res;
      };
      jStat.antidiag = function antidiag(arr) {
        var nrow = jStat.rows(arr) - 1;
        var res = new Array(nrow);
        for (var i = 0; nrow >= 0; nrow--, i++)
          res[i] = [arr[i][nrow]];
        return res;
      };
      jStat.transpose = function transpose(arr) {
        var obj = [];
        var objArr,
            rows,
            cols,
            j,
            i;
        if (!isArray(arr[0]))
          arr = [arr];
        rows = arr.length;
        cols = arr[0].length;
        for (i = 0; i < cols; i++) {
          objArr = new Array(rows);
          for (j = 0; j < rows; j++)
            objArr[j] = arr[j][i];
          obj.push(objArr);
        }
        return obj.length === 1 ? obj[0] : obj;
      };
      jStat.map = function map(arr, func, toAlter) {
        var row,
            nrow,
            ncol,
            res,
            col;
        if (!isArray(arr[0]))
          arr = [arr];
        nrow = arr.length;
        ncol = arr[0].length;
        res = toAlter ? arr : new Array(nrow);
        for (row = 0; row < nrow; row++) {
          if (!res[row])
            res[row] = new Array(ncol);
          for (col = 0; col < ncol; col++)
            res[row][col] = func(arr[row][col], row, col);
        }
        return res.length === 1 ? res[0] : res;
      };
      jStat.cumreduce = function cumreduce(arr, func, toAlter) {
        var row,
            nrow,
            ncol,
            res,
            col;
        if (!isArray(arr[0]))
          arr = [arr];
        nrow = arr.length;
        ncol = arr[0].length;
        res = toAlter ? arr : new Array(nrow);
        for (row = 0; row < nrow; row++) {
          if (!res[row])
            res[row] = new Array(ncol);
          if (ncol > 0)
            res[row][0] = arr[row][0];
          for (col = 1; col < ncol; col++)
            res[row][col] = func(res[row][col - 1], arr[row][col]);
        }
        return res.length === 1 ? res[0] : res;
      };
      jStat.alter = function alter(arr, func) {
        return jStat.map(arr, func, true);
      };
      jStat.create = function create(rows, cols, func) {
        var res = new Array(rows);
        var i,
            j;
        if (isFunction(cols)) {
          func = cols;
          cols = rows;
        }
        for (i = 0; i < rows; i++) {
          res[i] = new Array(cols);
          for (j = 0; j < cols; j++)
            res[i][j] = func(i, j);
        }
        return res;
      };
      function retZero() {
        return 0;
      }
      jStat.zeros = function zeros(rows, cols) {
        if (!isNumber(cols))
          cols = rows;
        return jStat.create(rows, cols, retZero);
      };
      function retOne() {
        return 1;
      }
      jStat.ones = function ones(rows, cols) {
        if (!isNumber(cols))
          cols = rows;
        return jStat.create(rows, cols, retOne);
      };
      jStat.rand = function rand(rows, cols) {
        if (!isNumber(cols))
          cols = rows;
        return jStat.create(rows, cols, Math.random);
      };
      function retIdent(i, j) {
        return i === j ? 1 : 0;
      }
      jStat.identity = function identity(rows, cols) {
        if (!isNumber(cols))
          cols = rows;
        return jStat.create(rows, cols, retIdent);
      };
      jStat.symmetric = function symmetric(arr) {
        var issymmetric = true;
        var size = arr.length;
        var row,
            col;
        if (arr.length !== arr[0].length)
          return false;
        for (row = 0; row < size; row++) {
          for (col = 0; col < size; col++)
            if (arr[col][row] !== arr[row][col])
              return false;
        }
        return true;
      };
      jStat.clear = function clear(arr) {
        return jStat.alter(arr, retZero);
      };
      jStat.seq = function seq(min, max, length, func) {
        if (!isFunction(func))
          func = false;
        var arr = [];
        var hival = calcRdx(min, max);
        var step = (max * hival - min * hival) / ((length - 1) * hival);
        var current = min;
        var cnt;
        for (cnt = 0; current <= max; cnt++, current = (min * hival + step * hival * cnt) / hival) {
          arr.push((func ? func(current, cnt) : current));
        }
        return arr;
      };
      var jProto = jStat.prototype;
      jProto.length = 0;
      jProto.push = Array.prototype.push;
      jProto.sort = Array.prototype.sort;
      jProto.splice = Array.prototype.splice;
      jProto.slice = Array.prototype.slice;
      jProto.toArray = function toArray() {
        return this.length > 1 ? slice.call(this) : slice.call(this)[0];
      };
      jProto.map = function map(func, toAlter) {
        return jStat(jStat.map(this, func, toAlter));
      };
      jProto.cumreduce = function cumreduce(func, toAlter) {
        return jStat(jStat.cumreduce(this, func, toAlter));
      };
      jProto.alter = function alter(func) {
        jStat.alter(this, func);
        return this;
      };
      (function(funcs) {
        for (var i = 0; i < funcs.length; i++)
          (function(passfunc) {
            jProto[passfunc] = function(func) {
              var self = this,
                  results;
              if (func) {
                setTimeout(function() {
                  func.call(self, jProto[passfunc].call(self));
                });
                return this;
              }
              results = jStat[passfunc](this);
              return isArray(results) ? jStat(results) : results;
            };
          })(funcs[i]);
      })('transpose clear symmetric rows cols dimensions diag antidiag'.split(' '));
      (function(funcs) {
        for (var i = 0; i < funcs.length; i++)
          (function(passfunc) {
            jProto[passfunc] = function(index, func) {
              var self = this;
              if (func) {
                setTimeout(function() {
                  func.call(self, jProto[passfunc].call(self, index));
                });
                return this;
              }
              return jStat(jStat[passfunc](this, index));
            };
          })(funcs[i]);
      })('row col'.split(' '));
      (function(funcs) {
        for (var i = 0; i < funcs.length; i++)
          (function(passfunc) {
            jProto[passfunc] = new Function('return jStat(jStat.' + passfunc + '.apply(null, arguments));');
          })(funcs[i]);
      })('create zeros ones rand identity'.split(' '));
      return jStat;
    }(Math));
    (function(jStat, Math) {
      var isFunction = jStat.utils.isFunction;
      function ascNum(a, b) {
        return a - b;
      }
      function clip(arg, min, max) {
        return Math.max(min, Math.min(arg, max));
      }
      jStat.sum = function sum(arr) {
        var sum = 0;
        var i = arr.length;
        var tmp;
        while (--i >= 0)
          sum += arr[i];
        return sum;
      };
      jStat.sumsqrd = function sumsqrd(arr) {
        var sum = 0;
        var i = arr.length;
        while (--i >= 0)
          sum += arr[i] * arr[i];
        return sum;
      };
      jStat.sumsqerr = function sumsqerr(arr) {
        var mean = jStat.mean(arr);
        var sum = 0;
        var i = arr.length;
        var tmp;
        while (--i >= 0) {
          tmp = arr[i] - mean;
          sum += tmp * tmp;
        }
        return sum;
      };
      jStat.product = function product(arr) {
        var prod = 1;
        var i = arr.length;
        while (--i >= 0)
          prod *= arr[i];
        return prod;
      };
      jStat.min = function min(arr) {
        var low = arr[0];
        var i = 0;
        while (++i < arr.length)
          if (arr[i] < low)
            low = arr[i];
        return low;
      };
      jStat.max = function max(arr) {
        var high = arr[0];
        var i = 0;
        while (++i < arr.length)
          if (arr[i] > high)
            high = arr[i];
        return high;
      };
      jStat.mean = function mean(arr) {
        return jStat.sum(arr) / arr.length;
      };
      jStat.meansqerr = function meansqerr(arr) {
        return jStat.sumsqerr(arr) / arr.length;
      };
      jStat.geomean = function geomean(arr) {
        return Math.pow(jStat.product(arr), 1 / arr.length);
      };
      jStat.median = function median(arr) {
        var arrlen = arr.length;
        var _arr = arr.slice().sort(ascNum);
        return !(arrlen & 1) ? (_arr[(arrlen / 2) - 1] + _arr[(arrlen / 2)]) / 2 : _arr[(arrlen / 2) | 0];
      };
      jStat.cumsum = function cumsum(arr) {
        return jStat.cumreduce(arr, function(a, b) {
          return a + b;
        });
      };
      jStat.cumprod = function cumprod(arr) {
        return jStat.cumreduce(arr, function(a, b) {
          return a * b;
        });
      };
      jStat.diff = function diff(arr) {
        var diffs = [];
        var arrLen = arr.length;
        var i;
        for (i = 1; i < arrLen; i++)
          diffs.push(arr[i] - arr[i - 1]);
        return diffs;
      };
      jStat.mode = function mode(arr) {
        var arrLen = arr.length;
        var _arr = arr.slice().sort(ascNum);
        var count = 1;
        var maxCount = 0;
        var numMaxCount = 0;
        var mode_arr = [];
        var i;
        for (i = 0; i < arrLen; i++) {
          if (_arr[i] === _arr[i + 1]) {
            count++;
          } else {
            if (count > maxCount) {
              mode_arr = [_arr[i]];
              maxCount = count;
              numMaxCount = 0;
            } else if (count === maxCount) {
              mode_arr.push(_arr[i]);
              numMaxCount++;
            }
            count = 1;
          }
        }
        return numMaxCount === 0 ? mode_arr[0] : mode_arr;
      };
      jStat.range = function range(arr) {
        return jStat.max(arr) - jStat.min(arr);
      };
      jStat.variance = function variance(arr, flag) {
        return jStat.sumsqerr(arr) / (arr.length - (flag ? 1 : 0));
      };
      jStat.stdev = function stdev(arr, flag) {
        return Math.sqrt(jStat.variance(arr, flag));
      };
      jStat.meandev = function meandev(arr) {
        var devSum = 0;
        var mean = jStat.mean(arr);
        var i;
        for (i = arr.length - 1; i >= 0; i--)
          devSum += Math.abs(arr[i] - mean);
        return devSum / arr.length;
      };
      jStat.meddev = function meddev(arr) {
        var devSum = 0;
        var median = jStat.median(arr);
        var i;
        for (i = arr.length - 1; i >= 0; i--)
          devSum += Math.abs(arr[i] - median);
        return devSum / arr.length;
      };
      jStat.coeffvar = function coeffvar(arr) {
        return jStat.stdev(arr) / jStat.mean(arr);
      };
      jStat.quartiles = function quartiles(arr) {
        var arrlen = arr.length;
        var _arr = arr.slice().sort(ascNum);
        return [_arr[Math.round((arrlen) / 4) - 1], _arr[Math.round((arrlen) / 2) - 1], _arr[Math.round((arrlen) * 3 / 4) - 1]];
      };
      jStat.quantiles = function quantiles(arr, quantilesArray, alphap, betap) {
        var sortedArray = arr.slice().sort(ascNum);
        var quantileVals = [quantilesArray.length];
        var n = arr.length;
        var i,
            p,
            m,
            aleph,
            k,
            gamma;
        if (typeof alphap === 'undefined')
          alphap = 3 / 8;
        if (typeof betap === 'undefined')
          betap = 3 / 8;
        for (i = 0; i < quantilesArray.length; i++) {
          p = quantilesArray[i];
          m = alphap + p * (1 - alphap - betap);
          aleph = n * p + m;
          k = Math.floor(clip(aleph, 1, n - 1));
          gamma = clip(aleph - k, 0, 1);
          quantileVals[i] = (1 - gamma) * sortedArray[k - 1] + gamma * sortedArray[k];
        }
        return quantileVals;
      };
      jStat.percentileOfScore = function percentileOfScore(arr, score, kind) {
        var counter = 0;
        var len = arr.length;
        var strict = false;
        var value,
            i;
        if (kind === 'strict')
          strict = true;
        for (i = 0; i < len; i++) {
          value = arr[i];
          if ((strict && value < score) || (!strict && value <= score)) {
            counter++;
          }
        }
        return counter / len;
      };
      jStat.histogram = function histogram(arr, bins) {
        var first = jStat.min(arr);
        var binCnt = bins || 4;
        var binWidth = (jStat.max(arr) - first) / binCnt;
        var len = arr.length;
        var bins = [];
        var i;
        for (i = 0; i < binCnt; i++)
          bins[i] = 0;
        for (i = 0; i < len; i++)
          bins[Math.min(Math.floor(((arr[i] - first) / binWidth)), binCnt - 1)] += 1;
        return bins;
      };
      jStat.covariance = function covariance(arr1, arr2) {
        var u = jStat.mean(arr1);
        var v = jStat.mean(arr2);
        var arr1Len = arr1.length;
        var sq_dev = new Array(arr1Len);
        var i;
        for (i = 0; i < arr1Len; i++)
          sq_dev[i] = (arr1[i] - u) * (arr2[i] - v);
        return jStat.sum(sq_dev) / (arr1Len - 1);
      };
      jStat.corrcoeff = function corrcoeff(arr1, arr2) {
        return jStat.covariance(arr1, arr2) / jStat.stdev(arr1, 1) / jStat.stdev(arr2, 1);
      };
      jStat.stanMoment = function stanMoment(arr, n) {
        var mu = jStat.mean(arr);
        var sigma = jStat.stdev(arr);
        var len = arr.length;
        var skewSum = 0;
        for (i = 0; i < len; i++)
          skewSum += Math.pow((arr[i] - mu) / sigma, n);
        return skewSum / arr.length;
      };
      jStat.skewness = function skewness(arr) {
        return jStat.stanMoment(arr, 3);
      };
      jStat.kurtosis = function kurtosis(arr) {
        return jStat.stanMoment(arr, 4) - 3;
      };
      var jProto = jStat.prototype;
      (function(funcs) {
        for (var i = 0; i < funcs.length; i++)
          (function(passfunc) {
            jProto[passfunc] = function(fullbool, func) {
              var arr = [];
              var i = 0;
              var tmpthis = this;
              if (isFunction(fullbool)) {
                func = fullbool;
                fullbool = false;
              }
              if (func) {
                setTimeout(function() {
                  func.call(tmpthis, jProto[passfunc].call(tmpthis, fullbool));
                });
                return this;
              }
              if (this.length > 1) {
                tmpthis = fullbool === true ? this : this.transpose();
                for (; i < tmpthis.length; i++)
                  arr[i] = jStat[passfunc](tmpthis[i]);
                return arr;
              }
              return jStat[passfunc](this[0], fullbool);
            };
          })(funcs[i]);
      })(('cumsum cumprod').split(' '));
      (function(funcs) {
        for (var i = 0; i < funcs.length; i++)
          (function(passfunc) {
            jProto[passfunc] = function(fullbool, func) {
              var arr = [];
              var i = 0;
              var tmpthis = this;
              if (isFunction(fullbool)) {
                func = fullbool;
                fullbool = false;
              }
              if (func) {
                setTimeout(function() {
                  func.call(tmpthis, jProto[passfunc].call(tmpthis, fullbool));
                });
                return this;
              }
              if (this.length > 1) {
                tmpthis = fullbool === true ? this : this.transpose();
                for (; i < tmpthis.length; i++)
                  arr[i] = jStat[passfunc](tmpthis[i]);
                return fullbool === true ? jStat[passfunc](jStat.utils.toVector(arr)) : arr;
              }
              return jStat[passfunc](this[0], fullbool);
            };
          })(funcs[i]);
      })(('sum sumsqrd sumsqerr product min max mean meansqerr geomean median diff ' + 'mode range variance stdev meandev meddev coeffvar quartiles histogram ' + 'skewness kurtosis').split(' '));
      (function(funcs) {
        for (var i = 0; i < funcs.length; i++)
          (function(passfunc) {
            jProto[passfunc] = function() {
              var arr = [];
              var i = 0;
              var tmpthis = this;
              var args = Array.prototype.slice.call(arguments);
              if (isFunction(args[args.length - 1])) {
                var callbackFunction = args[args.length - 1];
                var argsToPass = args.slice(0, args.length - 1);
                setTimeout(function() {
                  callbackFunction.call(tmpthis, jProto[passfunc].apply(tmpthis, argsToPass));
                });
                return this;
              } else {
                var callbackFunction = undefined;
                var curriedFunction = function curriedFunction(vector) {
                  return jStat[passfunc].apply(tmpthis, [vector].concat(args));
                };
              }
              if (this.length > 1) {
                tmpthis = tmpthis.transpose();
                for (; i < tmpthis.length; i++)
                  arr[i] = curriedFunction(tmpthis[i]);
                return arr;
              }
              return curriedFunction(this[0]);
            };
          })(funcs[i]);
      })('quantiles percentileOfScore'.split(' '));
    }(this.jStat, Math));
    (function(jStat, Math) {
      jStat.gammaln = function gammaln(x) {
        var j = 0;
        var cof = [76.18009172947146, -86.50532032941677, 24.01409824083091, -1.231739572450155, 0.1208650973866179e-2, -0.5395239384953e-5];
        var ser = 1.000000000190015;
        var xx,
            y,
            tmp;
        tmp = (y = xx = x) + 5.5;
        tmp -= (xx + 0.5) * Math.log(tmp);
        for (; j < 6; j++)
          ser += cof[j] / ++y;
        return Math.log(2.5066282746310005 * ser / xx) - tmp;
      };
      jStat.gammafn = function gammafn(x) {
        var p = [-1.716185138865495, 24.76565080557592, -379.80425647094563, 629.3311553128184, 866.9662027904133, -31451.272968848367, -36144.413418691176, 66456.14382024054];
        var q = [-30.8402300119739, 315.35062697960416, -1015.1563674902192, -3107.771671572311, 22538.118420980151, 4755.8462775278811, -134659.9598649693, -115132.2596755535];
        var fact = false;
        var n = 0;
        var xden = 0;
        var xnum = 0;
        var y = x;
        var i,
            z,
            yi,
            res,
            sum,
            ysq;
        if (y <= 0) {
          res = y % 1 + 3.6e-16;
          if (res) {
            fact = (!(y & 1) ? 1 : -1) * Math.PI / Math.sin(Math.PI * res);
            y = 1 - y;
          } else {
            return Infinity;
          }
        }
        yi = y;
        if (y < 1) {
          z = y++;
        } else {
          z = (y -= n = (y | 0) - 1) - 1;
        }
        for (i = 0; i < 8; ++i) {
          xnum = (xnum + p[i]) * z;
          xden = xden * z + q[i];
        }
        res = xnum / xden + 1;
        if (yi < y) {
          res /= yi;
        } else if (yi > y) {
          for (i = 0; i < n; ++i) {
            res *= y;
            y++;
          }
        }
        if (fact) {
          res = fact / res;
        }
        return res;
      };
      jStat.gammap = function gammap(a, x) {
        return jStat.lowRegGamma(a, x) * jStat.gammafn(a);
      };
      jStat.lowRegGamma = function lowRegGamma(a, x) {
        var aln = jStat.gammaln(a);
        var ap = a;
        var sum = 1 / a;
        var del = sum;
        var b = x + 1 - a;
        var c = 1 / 1.0e-30;
        var d = 1 / b;
        var h = d;
        var i = 1;
        var ITMAX = -~(Math.log((a >= 1) ? a : 1 / a) * 8.5 + a * 0.4 + 17);
        var an,
            endval;
        if (x < 0 || a <= 0) {
          return NaN;
        } else if (x < a + 1) {
          for (; i <= ITMAX; i++) {
            sum += del *= x / ++ap;
          }
          return (sum * Math.exp(-x + a * Math.log(x) - (aln)));
        }
        for (; i <= ITMAX; i++) {
          an = -i * (i - a);
          b += 2;
          d = an * d + b;
          c = b + an / c;
          d = 1 / d;
          h *= d * c;
        }
        return (1 - h * Math.exp(-x + a * Math.log(x) - (aln)));
      };
      jStat.factorialln = function factorialln(n) {
        return n < 0 ? NaN : jStat.gammaln(n + 1);
      };
      jStat.factorial = function factorial(n) {
        return n < 0 ? NaN : jStat.gammafn(n + 1);
      };
      jStat.combination = function combination(n, m) {
        return (n > 170 || m > 170) ? Math.exp(jStat.combinationln(n, m)) : (jStat.factorial(n) / jStat.factorial(m)) / jStat.factorial(n - m);
      };
      jStat.combinationln = function combinationln(n, m) {
        return jStat.factorialln(n) - jStat.factorialln(m) - jStat.factorialln(n - m);
      };
      jStat.permutation = function permutation(n, m) {
        return jStat.factorial(n) / jStat.factorial(n - m);
      };
      jStat.betafn = function betafn(x, y) {
        if (x <= 0 || y <= 0)
          return undefined;
        return (x + y > 170) ? Math.exp(jStat.betaln(x, y)) : jStat.gammafn(x) * jStat.gammafn(y) / jStat.gammafn(x + y);
      };
      jStat.betaln = function betaln(x, y) {
        return jStat.gammaln(x) + jStat.gammaln(y) - jStat.gammaln(x + y);
      };
      jStat.betacf = function betacf(x, a, b) {
        var fpmin = 1e-30;
        var m = 1;
        var qab = a + b;
        var qap = a + 1;
        var qam = a - 1;
        var c = 1;
        var d = 1 - qab * x / qap;
        var m2,
            aa,
            del,
            h;
        if (Math.abs(d) < fpmin)
          d = fpmin;
        d = 1 / d;
        h = d;
        for (; m <= 100; m++) {
          m2 = 2 * m;
          aa = m * (b - m) * x / ((qam + m2) * (a + m2));
          d = 1 + aa * d;
          if (Math.abs(d) < fpmin)
            d = fpmin;
          c = 1 + aa / c;
          if (Math.abs(c) < fpmin)
            c = fpmin;
          d = 1 / d;
          h *= d * c;
          aa = -(a + m) * (qab + m) * x / ((a + m2) * (qap + m2));
          d = 1 + aa * d;
          if (Math.abs(d) < fpmin)
            d = fpmin;
          c = 1 + aa / c;
          if (Math.abs(c) < fpmin)
            c = fpmin;
          d = 1 / d;
          del = d * c;
          h *= del;
          if (Math.abs(del - 1.0) < 3e-7)
            break;
        }
        return h;
      };
      jStat.gammapinv = function gammapinv(p, a) {
        var j = 0;
        var a1 = a - 1;
        var EPS = 1e-8;
        var gln = jStat.gammaln(a);
        var x,
            err,
            t,
            u,
            pp,
            lna1,
            afac;
        if (p >= 1)
          return Math.max(100, a + 100 * Math.sqrt(a));
        if (p <= 0)
          return 0;
        if (a > 1) {
          lna1 = Math.log(a1);
          afac = Math.exp(a1 * (lna1 - 1) - gln);
          pp = (p < 0.5) ? p : 1 - p;
          t = Math.sqrt(-2 * Math.log(pp));
          x = (2.30753 + t * 0.27061) / (1 + t * (0.99229 + t * 0.04481)) - t;
          if (p < 0.5)
            x = -x;
          x = Math.max(1e-3, a * Math.pow(1 - 1 / (9 * a) - x / (3 * Math.sqrt(a)), 3));
        } else {
          t = 1 - a * (0.253 + a * 0.12);
          if (p < t)
            x = Math.pow(p / t, 1 / a);
          else
            x = 1 - Math.log(1 - (p - t) / (1 - t));
        }
        for (; j < 12; j++) {
          if (x <= 0)
            return 0;
          err = jStat.lowRegGamma(a, x) - p;
          if (a > 1)
            t = afac * Math.exp(-(x - a1) + a1 * (Math.log(x) - lna1));
          else
            t = Math.exp(-x + a1 * Math.log(x) - gln);
          u = err / t;
          x -= (t = u / (1 - 0.5 * Math.min(1, u * ((a - 1) / x - 1))));
          if (x <= 0)
            x = 0.5 * (x + t);
          if (Math.abs(t) < EPS * x)
            break;
        }
        return x;
      };
      jStat.erf = function erf(x) {
        var cof = [-1.3026537197817094, 6.4196979235649026e-1, 1.9476473204185836e-2, -9.561514786808631e-3, -9.46595344482036e-4, 3.66839497852761e-4, 4.2523324806907e-5, -2.0278578112534e-5, -1.624290004647e-6, 1.303655835580e-6, 1.5626441722e-8, -8.5238095915e-8, 6.529054439e-9, 5.059343495e-9, -9.91364156e-10, -2.27365122e-10, 9.6467911e-11, 2.394038e-12, -6.886027e-12, 8.94487e-13, 3.13092e-13, -1.12708e-13, 3.81e-16, 7.106e-15, -1.523e-15, -9.4e-17, 1.21e-16, -2.8e-17];
        var j = cof.length - 1;
        var isneg = false;
        var d = 0;
        var dd = 0;
        var t,
            ty,
            tmp,
            res;
        if (x < 0) {
          x = -x;
          isneg = true;
        }
        t = 2 / (2 + x);
        ty = 4 * t - 2;
        for (; j > 0; j--) {
          tmp = d;
          d = ty * d - dd + cof[j];
          dd = tmp;
        }
        res = t * Math.exp(-x * x + 0.5 * (cof[0] + ty * d) - dd);
        return isneg ? res - 1 : 1 - res;
      };
      jStat.erfc = function erfc(x) {
        return 1 - jStat.erf(x);
      };
      jStat.erfcinv = function erfcinv(p) {
        var j = 0;
        var x,
            err,
            t,
            pp;
        if (p >= 2)
          return -100;
        if (p <= 0)
          return 100;
        pp = (p < 1) ? p : 2 - p;
        t = Math.sqrt(-2 * Math.log(pp / 2));
        x = -0.70711 * ((2.30753 + t * 0.27061) / (1 + t * (0.99229 + t * 0.04481)) - t);
        for (; j < 2; j++) {
          err = jStat.erfc(x) - pp;
          x += err / (1.12837916709551257 * Math.exp(-x * x) - x * err);
        }
        return (p < 1) ? x : -x;
      };
      jStat.ibetainv = function ibetainv(p, a, b) {
        var EPS = 1e-8;
        var a1 = a - 1;
        var b1 = b - 1;
        var j = 0;
        var lna,
            lnb,
            pp,
            t,
            u,
            err,
            x,
            al,
            h,
            w,
            afac;
        if (p <= 0)
          return 0;
        if (p >= 1)
          return 1;
        if (a >= 1 && b >= 1) {
          pp = (p < 0.5) ? p : 1 - p;
          t = Math.sqrt(-2 * Math.log(pp));
          x = (2.30753 + t * 0.27061) / (1 + t * (0.99229 + t * 0.04481)) - t;
          if (p < 0.5)
            x = -x;
          al = (x * x - 3) / 6;
          h = 2 / (1 / (2 * a - 1) + 1 / (2 * b - 1));
          w = (x * Math.sqrt(al + h) / h) - (1 / (2 * b - 1) - 1 / (2 * a - 1)) * (al + 5 / 6 - 2 / (3 * h));
          x = a / (a + b * Math.exp(2 * w));
        } else {
          lna = Math.log(a / (a + b));
          lnb = Math.log(b / (a + b));
          t = Math.exp(a * lna) / a;
          u = Math.exp(b * lnb) / b;
          w = t + u;
          if (p < t / w)
            x = Math.pow(a * w * p, 1 / a);
          else
            x = 1 - Math.pow(b * w * (1 - p), 1 / b);
        }
        afac = -jStat.gammaln(a) - jStat.gammaln(b) + jStat.gammaln(a + b);
        for (; j < 10; j++) {
          if (x === 0 || x === 1)
            return x;
          err = jStat.ibeta(x, a, b) - p;
          t = Math.exp(a1 * Math.log(x) + b1 * Math.log(1 - x) + afac);
          u = err / t;
          x -= (t = u / (1 - 0.5 * Math.min(1, u * (a1 / x - b1 / (1 - x)))));
          if (x <= 0)
            x = 0.5 * (x + t);
          if (x >= 1)
            x = 0.5 * (x + t + 1);
          if (Math.abs(t) < EPS * x && j > 0)
            break;
        }
        return x;
      };
      jStat.ibeta = function ibeta(x, a, b) {
        var bt = (x === 0 || x === 1) ? 0 : Math.exp(jStat.gammaln(a + b) - jStat.gammaln(a) - jStat.gammaln(b) + a * Math.log(x) + b * Math.log(1 - x));
        if (x < 0 || x > 1)
          return false;
        if (x < (a + 1) / (a + b + 2))
          return bt * jStat.betacf(x, a, b) / a;
        return 1 - bt * jStat.betacf(1 - x, b, a) / b;
      };
      jStat.randn = function randn(n, m) {
        var u,
            v,
            x,
            y,
            q,
            mat;
        if (!m)
          m = n;
        if (n)
          return jStat.create(n, m, function() {
            return jStat.randn();
          });
        do {
          u = Math.random();
          v = 1.7156 * (Math.random() - 0.5);
          x = u - 0.449871;
          y = Math.abs(v) + 0.386595;
          q = x * x + y * (0.19600 * y - 0.25472 * x);
        } while (q > 0.27597 && (q > 0.27846 || v * v > -4 * Math.log(u) * u * u));
        return v / u;
      };
      jStat.randg = function randg(shape, n, m) {
        var oalph = shape;
        var a1,
            a2,
            u,
            v,
            x,
            mat;
        if (!m)
          m = n;
        if (!shape)
          shape = 1;
        if (n) {
          mat = jStat.zeros(n, m);
          mat.alter(function() {
            return jStat.randg(shape);
          });
          return mat;
        }
        if (shape < 1)
          shape += 1;
        a1 = shape - 1 / 3;
        a2 = 1 / Math.sqrt(9 * a1);
        do {
          do {
            x = jStat.randn();
            v = 1 + a2 * x;
          } while (v <= 0);
          v = v * v * v;
          u = Math.random();
        } while (u > 1 - 0.331 * Math.pow(x, 4) && Math.log(u) > 0.5 * x * x + a1 * (1 - v + Math.log(v)));
        if (shape == oalph)
          return a1 * v;
        do {
          u = Math.random();
        } while (u === 0);
        return Math.pow(u, 1 / oalph) * a1 * v;
      };
      (function(funcs) {
        for (var i = 0; i < funcs.length; i++)
          (function(passfunc) {
            jStat.fn[passfunc] = function() {
              return jStat(jStat.map(this, function(value) {
                return jStat[passfunc](value);
              }));
            };
          })(funcs[i]);
      })('gammaln gammafn factorial factorialln'.split(' '));
      (function(funcs) {
        for (var i = 0; i < funcs.length; i++)
          (function(passfunc) {
            jStat.fn[passfunc] = function() {
              return jStat(jStat[passfunc].apply(null, arguments));
            };
          })(funcs[i]);
      })('randn'.split(' '));
    }(this.jStat, Math));
    (function(jStat, Math) {
      (function(list) {
        for (var i = 0; i < list.length; i++)
          (function(func) {
            jStat[func] = function(a, b, c) {
              if (!(this instanceof arguments.callee))
                return new arguments.callee(a, b, c);
              this._a = a;
              this._b = b;
              this._c = c;
              return this;
            };
            jStat.fn[func] = function(a, b, c) {
              var newthis = jStat[func](a, b, c);
              newthis.data = this;
              return newthis;
            };
            jStat[func].prototype.sample = function(arr) {
              var a = this._a;
              var b = this._b;
              var c = this._c;
              if (arr)
                return jStat.alter(arr, function() {
                  return jStat[func].sample(a, b, c);
                });
              else
                return jStat[func].sample(a, b, c);
            };
            (function(vals) {
              for (var i = 0; i < vals.length; i++)
                (function(fnfunc) {
                  jStat[func].prototype[fnfunc] = function(x) {
                    var a = this._a;
                    var b = this._b;
                    var c = this._c;
                    if (!x && x !== 0)
                      x = this.data;
                    if (typeof x !== 'number') {
                      return jStat.fn.map.call(x, function(x) {
                        return jStat[func][fnfunc](x, a, b, c);
                      });
                    }
                    return jStat[func][fnfunc](x, a, b, c);
                  };
                })(vals[i]);
            })('pdf cdf inv'.split(' '));
            (function(vals) {
              for (var i = 0; i < vals.length; i++)
                (function(fnfunc) {
                  jStat[func].prototype[fnfunc] = function() {
                    return jStat[func][fnfunc](this._a, this._b, this._c);
                  };
                })(vals[i]);
            })('mean median mode variance'.split(' '));
          })(list[i]);
      })(('beta centralF cauchy chisquare exponential gamma invgamma kumaraswamy ' + 'lognormal normal pareto studentt weibull uniform  binomial negbin hypgeom ' + 'poisson triangular').split(' '));
      jStat.extend(jStat.beta, {
        pdf: function pdf(x, alpha, beta) {
          if (x > 1 || x < 0)
            return 0;
          if (alpha == 1 && beta == 1)
            return 1;
          if (alpha < 512 || beta < 512) {
            return (Math.pow(x, alpha - 1) * Math.pow(1 - x, beta - 1)) / jStat.betafn(alpha, beta);
          } else {
            return Math.exp((alpha - 1) * Math.log(x) + (beta - 1) * Math.log(1 - x) - jStat.betaln(alpha, beta));
          }
        },
        cdf: function cdf(x, alpha, beta) {
          return (x > 1 || x < 0) ? (x > 1) * 1 : jStat.ibeta(x, alpha, beta);
        },
        inv: function inv(x, alpha, beta) {
          return jStat.ibetainv(x, alpha, beta);
        },
        mean: function mean(alpha, beta) {
          return alpha / (alpha + beta);
        },
        median: function median(alpha, beta) {
          throw new Error('median not yet implemented');
        },
        mode: function mode(alpha, beta) {
          return (alpha * beta) / (Math.pow(alpha + beta, 2) * (alpha + beta + 1));
        },
        sample: function sample(alpha, beta) {
          var u = jStat.randg(alpha);
          return u / (u + jStat.randg(beta));
        },
        variance: function variance(alpha, beta) {
          return (alpha * beta) / (Math.pow(alpha + beta, 2) * (alpha + beta + 1));
        }
      });
      jStat.extend(jStat.centralF, {
        pdf: function pdf(x, df1, df2) {
          var p,
              q,
              f;
          if (x < 0)
            return undefined;
          if (df1 <= 2) {
            if (df1 === 1 && df2 === 1) {
              return Infinity;
            }
            if (df1 === 2 && df2 === 1) {
              return 1;
            }
            return Math.sqrt((Math.pow(df1 * x, df1) * Math.pow(df2, df2)) / (Math.pow(df1 * x + df2, df1 + df2))) / (x * jStat.betafn(df1 / 2, df2 / 2));
          }
          p = (df1 * x) / (df2 + x * df1);
          q = df2 / (df2 + x * df1);
          f = df1 * q / 2.0;
          return f * jStat.binomial.pdf((df1 - 2) / 2, (df1 + df2 - 2) / 2, p);
        },
        cdf: function cdf(x, df1, df2) {
          return jStat.ibeta((df1 * x) / (df1 * x + df2), df1 / 2, df2 / 2);
        },
        inv: function inv(x, df1, df2) {
          return df2 / (df1 * (1 / jStat.ibetainv(x, df1 / 2, df2 / 2) - 1));
        },
        mean: function mean(df1, df2) {
          return (df2 > 2) ? df2 / (df2 - 2) : undefined;
        },
        mode: function mode(df1, df2) {
          return (df1 > 2) ? (df2 * (df1 - 2)) / (df1 * (df2 + 2)) : undefined;
        },
        sample: function sample(df1, df2) {
          var x1 = jStat.randg(df1 / 2) * 2;
          var x2 = jStat.randg(df2 / 2) * 2;
          return (x1 / df1) / (x2 / df2);
        },
        variance: function variance(df1, df2) {
          if (df2 <= 4)
            return undefined;
          return 2 * df2 * df2 * (df1 + df2 - 2) / (df1 * (df2 - 2) * (df2 - 2) * (df2 - 4));
        }
      });
      jStat.extend(jStat.cauchy, {
        pdf: function pdf(x, local, scale) {
          return (scale / (Math.pow(x - local, 2) + Math.pow(scale, 2))) / Math.PI;
        },
        cdf: function cdf(x, local, scale) {
          return Math.atan((x - local) / scale) / Math.PI + 0.5;
        },
        inv: function(p, local, scale) {
          return local + scale * Math.tan(Math.PI * (p - 0.5));
        },
        median: function median(local, scale) {
          return local;
        },
        mode: function mode(local, scale) {
          return local;
        },
        sample: function sample(local, scale) {
          return jStat.randn() * Math.sqrt(1 / (2 * jStat.randg(0.5))) * scale + local;
        }
      });
      jStat.extend(jStat.chisquare, {
        pdf: function pdf(x, dof) {
          return x === 0 ? 0 : Math.exp((dof / 2 - 1) * Math.log(x) - x / 2 - (dof / 2) * Math.log(2) - jStat.gammaln(dof / 2));
        },
        cdf: function cdf(x, dof) {
          return jStat.lowRegGamma(dof / 2, x / 2);
        },
        inv: function(p, dof) {
          return 2 * jStat.gammapinv(p, 0.5 * dof);
        },
        mean: function(dof) {
          return dof;
        },
        median: function median(dof) {
          return dof * Math.pow(1 - (2 / (9 * dof)), 3);
        },
        mode: function mode(dof) {
          return (dof - 2 > 0) ? dof - 2 : 0;
        },
        sample: function sample(dof) {
          return jStat.randg(dof / 2) * 2;
        },
        variance: function variance(dof) {
          return 2 * dof;
        }
      });
      jStat.extend(jStat.exponential, {
        pdf: function pdf(x, rate) {
          return x < 0 ? 0 : rate * Math.exp(-rate * x);
        },
        cdf: function cdf(x, rate) {
          return x < 0 ? 0 : 1 - Math.exp(-rate * x);
        },
        inv: function(p, rate) {
          return -Math.log(1 - p) / rate;
        },
        mean: function(rate) {
          return 1 / rate;
        },
        median: function(rate) {
          return (1 / rate) * Math.log(2);
        },
        mode: function mode(rate) {
          return 0;
        },
        sample: function sample(rate) {
          return -1 / rate * Math.log(Math.random());
        },
        variance: function(rate) {
          return Math.pow(rate, -2);
        }
      });
      jStat.extend(jStat.gamma, {
        pdf: function pdf(x, shape, scale) {
          return Math.exp((shape - 1) * Math.log(x) - x / scale - jStat.gammaln(shape) - shape * Math.log(scale));
        },
        cdf: function cdf(x, shape, scale) {
          return jStat.lowRegGamma(shape, x / scale);
        },
        inv: function(p, shape, scale) {
          return jStat.gammapinv(p, shape) * scale;
        },
        mean: function(shape, scale) {
          return shape * scale;
        },
        mode: function mode(shape, scale) {
          if (shape > 1)
            return (shape - 1) * scale;
          return undefined;
        },
        sample: function sample(shape, scale) {
          return jStat.randg(shape) * scale;
        },
        variance: function variance(shape, scale) {
          return shape * scale * scale;
        }
      });
      jStat.extend(jStat.invgamma, {
        pdf: function pdf(x, shape, scale) {
          return Math.exp(-(shape + 1) * Math.log(x) - scale / x - jStat.gammaln(shape) + shape * Math.log(scale));
        },
        cdf: function cdf(x, shape, scale) {
          return 1 - jStat.lowRegGamma(shape, scale / x);
        },
        inv: function(p, shape, scale) {
          return scale / jStat.gammapinv(1 - p, shape);
        },
        mean: function(shape, scale) {
          return (shape > 1) ? scale / (shape - 1) : undefined;
        },
        mode: function mode(shape, scale) {
          return scale / (shape + 1);
        },
        sample: function sample(shape, scale) {
          return scale / jStat.randg(shape);
        },
        variance: function variance(shape, scale) {
          if (shape <= 2)
            return undefined;
          return scale * scale / ((shape - 1) * (shape - 1) * (shape - 2));
        }
      });
      jStat.extend(jStat.kumaraswamy, {
        pdf: function pdf(x, alpha, beta) {
          return Math.exp(Math.log(alpha) + Math.log(beta) + (alpha - 1) * Math.log(x) + (beta - 1) * Math.log(1 - Math.pow(x, alpha)));
        },
        cdf: function cdf(x, alpha, beta) {
          return (1 - Math.pow(1 - Math.pow(x, alpha), beta));
        },
        mean: function(alpha, beta) {
          return (beta * jStat.gammafn(1 + 1 / alpha) * jStat.gammafn(beta)) / (jStat.gammafn(1 + 1 / alpha + beta));
        },
        median: function median(alpha, beta) {
          return Math.pow(1 - Math.pow(2, -1 / beta), 1 / alpha);
        },
        mode: function mode(alpha, beta) {
          if (!(alpha >= 1 && beta >= 1 && (alpha !== 1 && beta !== 1)))
            return undefined;
          return Math.pow((alpha - 1) / (alpha * beta - 1), 1 / alpha);
        },
        variance: function variance(alpha, beta) {
          throw new Error('variance not yet implemented');
        }
      });
      jStat.extend(jStat.lognormal, {
        pdf: function pdf(x, mu, sigma) {
          return Math.exp(-Math.log(x) - 0.5 * Math.log(2 * Math.PI) - Math.log(sigma) - Math.pow(Math.log(x) - mu, 2) / (2 * sigma * sigma));
        },
        cdf: function cdf(x, mu, sigma) {
          return 0.5 + (0.5 * jStat.erf((Math.log(x) - mu) / Math.sqrt(2 * sigma * sigma)));
        },
        inv: function(p, mu, sigma) {
          return Math.exp(-1.41421356237309505 * sigma * jStat.erfcinv(2 * p) + mu);
        },
        mean: function mean(mu, sigma) {
          return Math.exp(mu + sigma * sigma / 2);
        },
        median: function median(mu, sigma) {
          return Math.exp(mu);
        },
        mode: function mode(mu, sigma) {
          return Math.exp(mu - sigma * sigma);
        },
        sample: function sample(mu, sigma) {
          return Math.exp(jStat.randn() * sigma + mu);
        },
        variance: function variance(mu, sigma) {
          return (Math.exp(sigma * sigma) - 1) * Math.exp(2 * mu + sigma * sigma);
        }
      });
      jStat.extend(jStat.normal, {
        pdf: function pdf(x, mean, std) {
          return Math.exp(-0.5 * Math.log(2 * Math.PI) - Math.log(std) - Math.pow(x - mean, 2) / (2 * std * std));
        },
        cdf: function cdf(x, mean, std) {
          return 0.5 * (1 + jStat.erf((x - mean) / Math.sqrt(2 * std * std)));
        },
        inv: function(p, mean, std) {
          return -1.41421356237309505 * std * jStat.erfcinv(2 * p) + mean;
        },
        mean: function(mean, std) {
          return mean;
        },
        median: function median(mean, std) {
          return mean;
        },
        mode: function(mean, std) {
          return mean;
        },
        sample: function sample(mean, std) {
          return jStat.randn() * std + mean;
        },
        variance: function(mean, std) {
          return std * std;
        }
      });
      jStat.extend(jStat.pareto, {
        pdf: function pdf(x, scale, shape) {
          if (x < scale)
            return undefined;
          return (shape * Math.pow(scale, shape)) / Math.pow(x, shape + 1);
        },
        cdf: function cdf(x, scale, shape) {
          return 1 - Math.pow(scale / x, shape);
        },
        mean: function mean(scale, shape) {
          if (shape <= 1)
            return undefined;
          return (shape * Math.pow(scale, shape)) / (shape - 1);
        },
        median: function median(scale, shape) {
          return scale * (shape * Math.SQRT2);
        },
        mode: function mode(scale, shape) {
          return scale;
        },
        variance: function(scale, shape) {
          if (shape <= 2)
            return undefined;
          return (scale * scale * shape) / (Math.pow(shape - 1, 2) * (shape - 2));
        }
      });
      jStat.extend(jStat.studentt, {
        pdf: function pdf(x, dof) {
          return (jStat.gammafn((dof + 1) / 2) / (Math.sqrt(dof * Math.PI) * jStat.gammafn(dof / 2))) * Math.pow(1 + ((x * x) / dof), -((dof + 1) / 2));
        },
        cdf: function cdf(x, dof) {
          var dof2 = dof / 2;
          return jStat.ibeta((x + Math.sqrt(x * x + dof)) / (2 * Math.sqrt(x * x + dof)), dof2, dof2);
        },
        inv: function(p, dof) {
          var x = jStat.ibetainv(2 * Math.min(p, 1 - p), 0.5 * dof, 0.5);
          x = Math.sqrt(dof * (1 - x) / x);
          return (p > 0.5) ? x : -x;
        },
        mean: function mean(dof) {
          return (dof > 1) ? 0 : undefined;
        },
        median: function median(dof) {
          return 0;
        },
        mode: function mode(dof) {
          return 0;
        },
        sample: function sample(dof) {
          return jStat.randn() * Math.sqrt(dof / (2 * jStat.randg(dof / 2)));
        },
        variance: function variance(dof) {
          return (dof > 2) ? dof / (dof - 2) : (dof > 1) ? Infinity : undefined;
        }
      });
      jStat.extend(jStat.weibull, {
        pdf: function pdf(x, scale, shape) {
          if (x < 0)
            return 0;
          return (shape / scale) * Math.pow((x / scale), (shape - 1)) * Math.exp(-(Math.pow((x / scale), shape)));
        },
        cdf: function cdf(x, scale, shape) {
          return x < 0 ? 0 : 1 - Math.exp(-Math.pow((x / scale), shape));
        },
        inv: function(p, scale, shape) {
          return scale * Math.pow(-Math.log(1 - p), 1 / shape);
        },
        mean: function(scale, shape) {
          return scale * jStat.gammafn(1 + 1 / shape);
        },
        median: function median(scale, shape) {
          return scale * Math.pow(Math.log(2), 1 / shape);
        },
        mode: function mode(scale, shape) {
          if (shape <= 1)
            return undefined;
          return scale * Math.pow((shape - 1) / shape, 1 / shape);
        },
        sample: function sample(scale, shape) {
          return scale * Math.pow(-Math.log(Math.random()), 1 / shape);
        },
        variance: function variance(scale, shape) {
          return scale * scale * jStat.gammafn(1 + 2 / shape) - Math.pow(this.mean(scale, shape), 2);
        }
      });
      jStat.extend(jStat.uniform, {
        pdf: function pdf(x, a, b) {
          return (x < a || x > b) ? 0 : 1 / (b - a);
        },
        cdf: function cdf(x, a, b) {
          if (x < a)
            return 0;
          else if (x < b)
            return (x - a) / (b - a);
          return 1;
        },
        inv: function(p, a, b) {
          return a + (p * (b - a));
        },
        mean: function mean(a, b) {
          return 0.5 * (a + b);
        },
        median: function median(a, b) {
          return jStat.mean(a, b);
        },
        mode: function mode(a, b) {
          throw new Error('mode is not yet implemented');
        },
        sample: function sample(a, b) {
          return (a / 2 + b / 2) + (b / 2 - a / 2) * (2 * Math.random() - 1);
        },
        variance: function variance(a, b) {
          return Math.pow(b - a, 2) / 12;
        }
      });
      jStat.extend(jStat.binomial, {
        pdf: function pdf(k, n, p) {
          return (p === 0 || p === 1) ? ((n * p) === k ? 1 : 0) : jStat.combination(n, k) * Math.pow(p, k) * Math.pow(1 - p, n - k);
        },
        cdf: function cdf(x, n, p) {
          var binomarr = [],
              k = 0;
          if (x < 0) {
            return 0;
          }
          if (x < n) {
            for (; k <= x; k++) {
              binomarr[k] = jStat.binomial.pdf(k, n, p);
            }
            return jStat.sum(binomarr);
          }
          return 1;
        }
      });
      jStat.extend(jStat.negbin, {
        pdf: function pdf(k, r, p) {
          return k !== k | 0 ? false : k < 0 ? 0 : jStat.combination(k + r - 1, r - 1) * Math.pow(1 - p, k) * Math.pow(p, r);
        },
        cdf: function cdf(x, r, p) {
          var sum = 0,
              k = 0;
          if (x < 0)
            return 0;
          for (; k <= x; k++) {
            sum += jStat.negbin.pdf(k, r, p);
          }
          return sum;
        }
      });
      jStat.extend(jStat.hypgeom, {
        pdf: function pdf(k, N, m, n) {
          if (k !== k | 0) {
            return false;
          } else if (k < 0 || k < m - (N - n)) {
            return 0;
          } else if (k > n || k > m) {
            return 0;
          } else if (m * 2 > N) {
            if (n * 2 > N) {
              return jStat.hypgeom.pdf(N - m - n + k, N, N - m, N - n);
            } else {
              return jStat.hypgeom.pdf(n - k, N, N - m, n);
            }
          } else if (n * 2 > N) {
            return jStat.hypgeom.pdf(m - k, N, m, N - n);
          } else if (m < n) {
            return jStat.hypgeom.pdf(k, N, n, m);
          } else {
            var scaledPDF = 1;
            var samplesDone = 0;
            for (var i = 0; i < k; i++) {
              while (scaledPDF > 1 && samplesDone < n) {
                scaledPDF *= 1 - (m / (N - samplesDone));
                samplesDone++;
              }
              scaledPDF *= (n - i) * (m - i) / ((i + 1) * (N - m - n + i + 1));
            }
            for (; samplesDone < n; samplesDone++) {
              scaledPDF *= 1 - (m / (N - samplesDone));
            }
            return Math.min(1, Math.max(0, scaledPDF));
          }
        },
        cdf: function cdf(x, N, m, n) {
          if (x < 0 || x < m - (N - n)) {
            return 0;
          } else if (x >= n || x >= m) {
            return 1;
          } else if (m * 2 > N) {
            if (n * 2 > N) {
              return jStat.hypgeom.cdf(N - m - n + x, N, N - m, N - n);
            } else {
              return 1 - jStat.hypgeom.cdf(n - x - 1, N, N - m, n);
            }
          } else if (n * 2 > N) {
            return 1 - jStat.hypgeom.cdf(m - x - 1, N, m, N - n);
          } else if (m < n) {
            return jStat.hypgeom.cdf(x, N, n, m);
          } else {
            var scaledCDF = 1;
            var scaledPDF = 1;
            var samplesDone = 0;
            for (var i = 0; i < x; i++) {
              while (scaledCDF > 1 && samplesDone < n) {
                var factor = 1 - (m / (N - samplesDone));
                scaledPDF *= factor;
                scaledCDF *= factor;
                samplesDone++;
              }
              scaledPDF *= (n - i) * (m - i) / ((i + 1) * (N - m - n + i + 1));
              scaledCDF += scaledPDF;
            }
            for (; samplesDone < n; samplesDone++) {
              scaledCDF *= 1 - (m / (N - samplesDone));
            }
            return Math.min(1, Math.max(0, scaledCDF));
          }
        }
      });
      jStat.extend(jStat.poisson, {
        pdf: function pdf(k, l) {
          return Math.pow(l, k) * Math.exp(-l) / jStat.factorial(k);
        },
        cdf: function cdf(x, l) {
          var sumarr = [],
              k = 0;
          if (x < 0)
            return 0;
          for (; k <= x; k++) {
            sumarr.push(jStat.poisson.pdf(k, l));
          }
          return jStat.sum(sumarr);
        },
        mean: function(l) {
          return l;
        },
        variance: function(l) {
          return l;
        },
        sample: function sample(l) {
          var p = 1,
              k = 0,
              L = Math.exp(-l);
          do {
            k++;
            p *= Math.random();
          } while (p > L);
          return k - 1;
        }
      });
      jStat.extend(jStat.triangular, {
        pdf: function pdf(x, a, b, c) {
          if (b <= a || c < a || c > b) {
            return undefined;
          } else {
            if (x < a || x > b) {
              return 0;
            } else {
              if (x <= c) {
                if (c === a)
                  return 1;
                else
                  return (2 * (x - a)) / ((b - a) * (c - a));
              } else {
                if (c === b)
                  return 1;
                else
                  return (2 * (b - x)) / ((b - a) * (b - c));
              }
            }
          }
        },
        cdf: function cdf(x, a, b, c) {
          if (b <= a || c < a || c > b)
            return undefined;
          if (x < a) {
            return 0;
          } else {
            if (x <= c)
              return Math.pow(x - a, 2) / ((b - a) * (c - a));
            return 1 - Math.pow(b - x, 2) / ((b - a) * (b - c));
          }
          return 1;
        },
        mean: function mean(a, b, c) {
          return (a + b + c) / 3;
        },
        median: function median(a, b, c) {
          if (c <= (a + b) / 2) {
            return b - Math.sqrt((b - a) * (b - c)) / Math.sqrt(2);
          } else if (c > (a + b) / 2) {
            return a + Math.sqrt((b - a) * (c - a)) / Math.sqrt(2);
          }
        },
        mode: function mode(a, b, c) {
          return c;
        },
        sample: function sample(a, b, c) {
          var u = Math.random();
          if (u < ((c - a) / (b - a)))
            return a + Math.sqrt(u * (b - a) * (c - a));
          return b - Math.sqrt((1 - u) * (b - a) * (b - c));
        },
        variance: function variance(a, b, c) {
          return (a * a + b * b + c * c - a * b - a * c - b * c) / 18;
        }
      });
    }(this.jStat, Math));
    (function(jStat, Math) {
      var push = Array.prototype.push;
      var isArray = jStat.utils.isArray;
      jStat.extend({
        add: function add(arr, arg) {
          if (isArray(arg)) {
            if (!isArray(arg[0]))
              arg = [arg];
            return jStat.map(arr, function(value, row, col) {
              return value + arg[row][col];
            });
          }
          return jStat.map(arr, function(value) {
            return value + arg;
          });
        },
        subtract: function subtract(arr, arg) {
          if (isArray(arg)) {
            if (!isArray(arg[0]))
              arg = [arg];
            return jStat.map(arr, function(value, row, col) {
              return value - arg[row][col] || 0;
            });
          }
          return jStat.map(arr, function(value) {
            return value - arg;
          });
        },
        divide: function divide(arr, arg) {
          if (isArray(arg)) {
            if (!isArray(arg[0]))
              arg = [arg];
            return jStat.multiply(arr, jStat.inv(arg));
          }
          return jStat.map(arr, function(value) {
            return value / arg;
          });
        },
        multiply: function multiply(arr, arg) {
          var row,
              col,
              nrescols,
              sum,
              nrow = arr.length,
              ncol = arr[0].length,
              res = jStat.zeros(nrow, nrescols = (isArray(arg)) ? arg[0].length : ncol),
              rescols = 0;
          if (isArray(arg)) {
            for (; rescols < nrescols; rescols++) {
              for (row = 0; row < nrow; row++) {
                sum = 0;
                for (col = 0; col < ncol; col++)
                  sum += arr[row][col] * arg[col][rescols];
                res[row][rescols] = sum;
              }
            }
            return (nrow === 1 && rescols === 1) ? res[0][0] : res;
          }
          return jStat.map(arr, function(value) {
            return value * arg;
          });
        },
        dot: function dot(arr, arg) {
          if (!isArray(arr[0]))
            arr = [arr];
          if (!isArray(arg[0]))
            arg = [arg];
          var left = (arr[0].length === 1 && arr.length !== 1) ? jStat.transpose(arr) : arr,
              right = (arg[0].length === 1 && arg.length !== 1) ? jStat.transpose(arg) : arg,
              res = [],
              row = 0,
              nrow = left.length,
              ncol = left[0].length,
              sum,
              col;
          for (; row < nrow; row++) {
            res[row] = [];
            sum = 0;
            for (col = 0; col < ncol; col++)
              sum += left[row][col] * right[row][col];
            res[row] = sum;
          }
          return (res.length === 1) ? res[0] : res;
        },
        pow: function pow(arr, arg) {
          return jStat.map(arr, function(value) {
            return Math.pow(value, arg);
          });
        },
        exp: function exp(arr) {
          return jStat.map(arr, function(value) {
            return Math.exp(value);
          });
        },
        log: function exp(arr) {
          return jStat.map(arr, function(value) {
            return Math.log(value);
          });
        },
        abs: function abs(arr) {
          return jStat.map(arr, function(value) {
            return Math.abs(value);
          });
        },
        norm: function norm(arr, p) {
          var nnorm = 0,
              i = 0;
          if (isNaN(p))
            p = 2;
          if (isArray(arr[0]))
            arr = arr[0];
          for (; i < arr.length; i++) {
            nnorm += Math.pow(Math.abs(arr[i]), p);
          }
          return Math.pow(nnorm, 1 / p);
        },
        angle: function angle(arr, arg) {
          return Math.acos(jStat.dot(arr, arg) / (jStat.norm(arr) * jStat.norm(arg)));
        },
        aug: function aug(a, b) {
          var newarr = a.slice(),
              i = 0;
          for (; i < newarr.length; i++) {
            push.apply(newarr[i], b[i]);
          }
          return newarr;
        },
        inv: function inv(a) {
          var rows = a.length;
          var cols = a[0].length;
          var b = jStat.identity(rows, cols);
          var c = jStat.gauss_jordan(a, b);
          var result = [];
          var i = 0;
          var j;
          for (; i < rows; i++) {
            result[i] = [];
            for (j = cols; j < c[0].length; j++)
              result[i][j - cols] = c[i][j];
          }
          return result;
        },
        det: function det(a) {
          var alen = a.length,
              alend = alen * 2,
              vals = new Array(alend),
              rowshift = alen - 1,
              colshift = alend - 1,
              mrow = rowshift - alen + 1,
              mcol = colshift,
              i = 0,
              result = 0,
              j;
          if (alen === 2) {
            return a[0][0] * a[1][1] - a[0][1] * a[1][0];
          }
          for (; i < alend; i++) {
            vals[i] = 1;
          }
          for (i = 0; i < alen; i++) {
            for (j = 0; j < alen; j++) {
              vals[(mrow < 0) ? mrow + alen : mrow] *= a[i][j];
              vals[(mcol < alen) ? mcol + alen : mcol] *= a[i][j];
              mrow++;
              mcol--;
            }
            mrow = --rowshift - alen + 1;
            mcol = --colshift;
          }
          for (i = 0; i < alen; i++) {
            result += vals[i];
          }
          for (; i < alend; i++) {
            result -= vals[i];
          }
          return result;
        },
        gauss_elimination: function gauss_elimination(a, b) {
          var i = 0,
              j = 0,
              n = a.length,
              m = a[0].length,
              factor = 1,
              sum = 0,
              x = [],
              maug,
              pivot,
              temp,
              k;
          a = jStat.aug(a, b);
          maug = a[0].length;
          for (i = 0; i < n; i++) {
            pivot = a[i][i];
            j = i;
            for (k = i + 1; k < m; k++) {
              if (pivot < Math.abs(a[k][i])) {
                pivot = a[k][i];
                j = k;
              }
            }
            if (j != i) {
              for (k = 0; k < maug; k++) {
                temp = a[i][k];
                a[i][k] = a[j][k];
                a[j][k] = temp;
              }
            }
            for (j = i + 1; j < n; j++) {
              factor = a[j][i] / a[i][i];
              for (k = i; k < maug; k++) {
                a[j][k] = a[j][k] - factor * a[i][k];
              }
            }
          }
          for (i = n - 1; i >= 0; i--) {
            sum = 0;
            for (j = i + 1; j <= n - 1; j++) {
              sum = sum + x[j] * a[i][j];
            }
            x[i] = (a[i][maug - 1] - sum) / a[i][i];
          }
          return x;
        },
        gauss_jordan: function gauss_jordan(a, b) {
          var m = jStat.aug(a, b),
              h = m.length,
              w = m[0].length;
          for (var y = 0; y < h; y++) {
            var maxrow = y;
            for (var y2 = y + 1; y2 < h; y2++) {
              if (Math.abs(m[y2][y]) > Math.abs(m[maxrow][y]))
                maxrow = y2;
            }
            var tmp = m[y];
            m[y] = m[maxrow];
            m[maxrow] = tmp;
            for (var y2 = y + 1; y2 < h; y2++) {
              c = m[y2][y] / m[y][y];
              for (var x = y; x < w; x++) {
                m[y2][x] -= m[y][x] * c;
              }
            }
          }
          for (var y = h - 1; y >= 0; y--) {
            c = m[y][y];
            for (var y2 = 0; y2 < y; y2++) {
              for (var x = w - 1; x > y - 1; x--) {
                m[y2][x] -= m[y][x] * m[y2][y] / c;
              }
            }
            m[y][y] /= c;
            for (var x = h; x < w; x++) {
              m[y][x] /= c;
            }
          }
          return m;
        },
        lu: function lu(a, b) {
          throw new Error('lu not yet implemented');
        },
        cholesky: function cholesky(a, b) {
          throw new Error('cholesky not yet implemented');
        },
        gauss_jacobi: function gauss_jacobi(a, b, x, r) {
          var i = 0;
          var j = 0;
          var n = a.length;
          var l = [];
          var u = [];
          var d = [];
          var xv,
              c,
              h,
              xk;
          for (; i < n; i++) {
            l[i] = [];
            u[i] = [];
            d[i] = [];
            for (j = 0; j < n; j++) {
              if (i > j) {
                l[i][j] = a[i][j];
                u[i][j] = d[i][j] = 0;
              } else if (i < j) {
                u[i][j] = a[i][j];
                l[i][j] = d[i][j] = 0;
              } else {
                d[i][j] = a[i][j];
                l[i][j] = u[i][j] = 0;
              }
            }
          }
          h = jStat.multiply(jStat.multiply(jStat.inv(d), jStat.add(l, u)), -1);
          c = jStat.multiply(jStat.inv(d), b);
          xv = x;
          xk = jStat.add(jStat.multiply(h, x), c);
          i = 2;
          while (Math.abs(jStat.norm(jStat.subtract(xk, xv))) > r) {
            xv = xk;
            xk = jStat.add(jStat.multiply(h, xv), c);
            i++;
          }
          return xk;
        },
        gauss_seidel: function gauss_seidel(a, b, x, r) {
          var i = 0;
          var n = a.length;
          var l = [];
          var u = [];
          var d = [];
          var j,
              xv,
              c,
              h,
              xk;
          for (; i < n; i++) {
            l[i] = [];
            u[i] = [];
            d[i] = [];
            for (j = 0; j < n; j++) {
              if (i > j) {
                l[i][j] = a[i][j];
                u[i][j] = d[i][j] = 0;
              } else if (i < j) {
                u[i][j] = a[i][j];
                l[i][j] = d[i][j] = 0;
              } else {
                d[i][j] = a[i][j];
                l[i][j] = u[i][j] = 0;
              }
            }
          }
          h = jStat.multiply(jStat.multiply(jStat.inv(jStat.add(d, l)), u), -1);
          c = jStat.multiply(jStat.inv(jStat.add(d, l)), b);
          xv = x;
          xk = jStat.add(jStat.multiply(h, x), c);
          i = 2;
          while (Math.abs(jStat.norm(jStat.subtract(xk, xv))) > r) {
            xv = xk;
            xk = jStat.add(jStat.multiply(h, xv), c);
            i = i + 1;
          }
          return xk;
        },
        SOR: function SOR(a, b, x, r, w) {
          var i = 0;
          var n = a.length;
          var l = [];
          var u = [];
          var d = [];
          var j,
              xv,
              c,
              h,
              xk;
          for (; i < n; i++) {
            l[i] = [];
            u[i] = [];
            d[i] = [];
            for (j = 0; j < n; j++) {
              if (i > j) {
                l[i][j] = a[i][j];
                u[i][j] = d[i][j] = 0;
              } else if (i < j) {
                u[i][j] = a[i][j];
                l[i][j] = d[i][j] = 0;
              } else {
                d[i][j] = a[i][j];
                l[i][j] = u[i][j] = 0;
              }
            }
          }
          h = jStat.multiply(jStat.inv(jStat.add(d, jStat.multiply(l, w))), jStat.subtract(jStat.multiply(d, 1 - w), jStat.multiply(u, w)));
          c = jStat.multiply(jStat.multiply(jStat.inv(jStat.add(d, jStat.multiply(l, w))), b), w);
          xv = x;
          xk = jStat.add(jStat.multiply(h, x), c);
          i = 2;
          while (Math.abs(jStat.norm(jStat.subtract(xk, xv))) > r) {
            xv = xk;
            xk = jStat.add(jStat.multiply(h, xv), c);
            i++;
          }
          return xk;
        },
        householder: function householder(a) {
          var m = a.length;
          var n = a[0].length;
          var i = 0;
          var w = [];
          var p = [];
          var alpha,
              r,
              k,
              j,
              factor;
          for (; i < m - 1; i++) {
            alpha = 0;
            for (j = i + 1; j < n; j++)
              alpha += (a[j][i] * a[j][i]);
            factor = (a[i + 1][i] > 0) ? -1 : 1;
            alpha = factor * Math.sqrt(alpha);
            r = Math.sqrt((((alpha * alpha) - a[i + 1][i] * alpha) / 2));
            w = jStat.zeros(m, 1);
            w[i + 1][0] = (a[i + 1][i] - alpha) / (2 * r);
            for (k = i + 2; k < m; k++)
              w[k][0] = a[k][i] / (2 * r);
            p = jStat.subtract(jStat.identity(m, n), jStat.multiply(jStat.multiply(w, jStat.transpose(w)), 2));
            a = jStat.multiply(p, jStat.multiply(a, p));
          }
          return a;
        },
        QR: function QR(a, b) {
          var m = a.length;
          var n = a[0].length;
          var i = 0;
          var w = [];
          var p = [];
          var x = [];
          var j,
              alpha,
              r,
              k,
              factor,
              sum;
          for (; i < m - 1; i++) {
            alpha = 0;
            for (j = i + 1; j < n; j++)
              alpha += (a[j][i] * a[j][i]);
            factor = (a[i + 1][i] > 0) ? -1 : 1;
            alpha = factor * Math.sqrt(alpha);
            r = Math.sqrt((((alpha * alpha) - a[i + 1][i] * alpha) / 2));
            w = jStat.zeros(m, 1);
            w[i + 1][0] = (a[i + 1][i] - alpha) / (2 * r);
            for (k = i + 2; k < m; k++)
              w[k][0] = a[k][i] / (2 * r);
            p = jStat.subtract(jStat.identity(m, n), jStat.multiply(jStat.multiply(w, jStat.transpose(w)), 2));
            a = jStat.multiply(p, a);
            b = jStat.multiply(p, b);
          }
          for (i = m - 1; i >= 0; i--) {
            sum = 0;
            for (j = i + 1; j <= n - 1; j++)
              sum = x[j] * a[i][j];
            x[i] = b[i][0] / a[i][i];
          }
          return x;
        },
        jacobi: function jacobi(a) {
          var condition = 1;
          var count = 0;
          var n = a.length;
          var e = jStat.identity(n, n);
          var ev = [];
          var b,
              i,
              j,
              p,
              q,
              maxim,
              theta,
              s;
          while (condition === 1) {
            count++;
            maxim = a[0][1];
            p = 0;
            q = 1;
            for (i = 0; i < n; i++) {
              for (j = 0; j < n; j++) {
                if (i != j) {
                  if (maxim < Math.abs(a[i][j])) {
                    maxim = Math.abs(a[i][j]);
                    p = i;
                    q = j;
                  }
                }
              }
            }
            if (a[p][p] === a[q][q])
              theta = (a[p][q] > 0) ? Math.PI / 4 : -Math.PI / 4;
            else
              theta = Math.atan(2 * a[p][q] / (a[p][p] - a[q][q])) / 2;
            s = jStat.identity(n, n);
            s[p][p] = Math.cos(theta);
            s[p][q] = -Math.sin(theta);
            s[q][p] = Math.sin(theta);
            s[q][q] = Math.cos(theta);
            e = jStat.multiply(e, s);
            b = jStat.multiply(jStat.multiply(jStat.inv(s), a), s);
            a = b;
            condition = 0;
            for (i = 1; i < n; i++) {
              for (j = 1; j < n; j++) {
                if (i != j && Math.abs(a[i][j]) > 0.001) {
                  condition = 1;
                }
              }
            }
          }
          for (i = 0; i < n; i++)
            ev.push(a[i][i]);
          return [e, ev];
        },
        rungekutta: function rungekutta(f, h, p, t_j, u_j, order) {
          var k1,
              k2,
              u_j1,
              k3,
              k4;
          if (order === 2) {
            while (t_j <= p) {
              k1 = h * f(t_j, u_j);
              k2 = h * f(t_j + h, u_j + k1);
              u_j1 = u_j + (k1 + k2) / 2;
              u_j = u_j1;
              t_j = t_j + h;
            }
          }
          if (order === 4) {
            while (t_j <= p) {
              k1 = h * f(t_j, u_j);
              k2 = h * f(t_j + h / 2, u_j + k1 / 2);
              k3 = h * f(t_j + h / 2, u_j + k2 / 2);
              k4 = h * f(t_j + h, u_j + k3);
              u_j1 = u_j + (k1 + 2 * k2 + 2 * k3 + k4) / 6;
              u_j = u_j1;
              t_j = t_j + h;
            }
          }
          return u_j;
        },
        romberg: function romberg(f, a, b, order) {
          var i = 0;
          var h = (b - a) / 2;
          var x = [];
          var h1 = [];
          var g = [];
          var m,
              a1,
              j,
              k,
              I,
              d;
          while (i < order / 2) {
            I = f(a);
            for (j = a, k = 0; j <= b; j = j + h, k++)
              x[k] = j;
            m = x.length;
            for (j = 1; j < m - 1; j++) {
              I += (((j % 2) !== 0) ? 4 : 2) * f(x[j]);
            }
            I = (h / 3) * (I + f(b));
            g[i] = I;
            h /= 2;
            i++;
          }
          a1 = g.length;
          m = 1;
          while (a1 !== 1) {
            for (j = 0; j < a1 - 1; j++)
              h1[j] = ((Math.pow(4, m)) * g[j + 1] - g[j]) / (Math.pow(4, m) - 1);
            a1 = h1.length;
            g = h1;
            h1 = [];
            m++;
          }
          return g;
        },
        richardson: function richardson(X, f, x, h) {
          function pos(X, x) {
            var i = 0;
            var n = X.length;
            var p;
            for (; i < n; i++)
              if (X[i] === x)
                p = i;
            return p;
          }
          var n = X.length,
              h_min = Math.abs(x - X[pos(X, x) + 1]),
              i = 0,
              g = [],
              h1 = [],
              y1,
              y2,
              m,
              a,
              j;
          while (h >= h_min) {
            y1 = pos(X, x + h);
            y2 = pos(X, x);
            g[i] = (f[y1] - 2 * f[y2] + f[2 * y2 - y1]) / (h * h);
            h /= 2;
            i++;
          }
          a = g.length;
          m = 1;
          while (a != 1) {
            for (j = 0; j < a - 1; j++)
              h1[j] = ((Math.pow(4, m)) * g[j + 1] - g[j]) / (Math.pow(4, m) - 1);
            a = h1.length;
            g = h1;
            h1 = [];
            m++;
          }
          return g;
        },
        simpson: function simpson(f, a, b, n) {
          var h = (b - a) / n;
          var I = f(a);
          var x = [];
          var j = a;
          var k = 0;
          var i = 1;
          var m;
          for (; j <= b; j = j + h, k++)
            x[k] = j;
          m = x.length;
          for (; i < m - 1; i++) {
            I += ((i % 2 !== 0) ? 4 : 2) * f(x[i]);
          }
          return (h / 3) * (I + f(b));
        },
        hermite: function hermite(X, F, dF, value) {
          var n = X.length;
          var p = 0;
          var i = 0;
          var l = [];
          var dl = [];
          var A = [];
          var B = [];
          var j;
          for (; i < n; i++) {
            l[i] = 1;
            for (j = 0; j < n; j++) {
              if (i != j)
                l[i] *= (value - X[j]) / (X[i] - X[j]);
            }
            dl[i] = 0;
            for (j = 0; j < n; j++) {
              if (i != j)
                dl[i] += 1 / (X[i] - X[j]);
            }
            A[i] = (1 - 2 * (value - X[i]) * dl[i]) * (l[i] * l[i]);
            B[i] = (value - X[i]) * (l[i] * l[i]);
            p += (A[i] * F[i] + B[i] * dF[i]);
          }
          return p;
        },
        lagrange: function lagrange(X, F, value) {
          var p = 0;
          var i = 0;
          var j,
              l;
          var n = X.length;
          for (; i < n; i++) {
            l = F[i];
            for (j = 0; j < n; j++) {
              if (i != j)
                l *= (value - X[j]) / (X[i] - X[j]);
            }
            p += l;
          }
          return p;
        },
        cubic_spline: function cubic_spline(X, F, value) {
          var n = X.length;
          var i = 0,
              j;
          var A = [];
          var B = [];
          var alpha = [];
          var c = [];
          var h = [];
          var b = [];
          var d = [];
          for (; i < n - 1; i++)
            h[i] = X[i + 1] - X[i];
          alpha[0] = 0;
          for (i = 1; i < n - 1; i++) {
            alpha[i] = (3 / h[i]) * (F[i + 1] - F[i]) - (3 / h[i - 1]) * (F[i] - F[i - 1]);
          }
          for (i = 1; i < n - 1; i++) {
            A[i] = [];
            B[i] = [];
            A[i][i - 1] = h[i - 1];
            A[i][i] = 2 * (h[i - 1] + h[i]);
            A[i][i + 1] = h[i];
            B[i][0] = alpha[i];
          }
          c = jStat.multiply(jStat.inv(A), B);
          for (j = 0; j < n - 1; j++) {
            b[j] = (F[j + 1] - F[j]) / h[j] - h[j] * (c[j + 1][0] + 2 * c[j][0]) / 3;
            d[j] = (c[j + 1][0] - c[j][0]) / (3 * h[j]);
          }
          for (j = 0; j < n; j++) {
            if (X[j] > value)
              break;
          }
          j -= 1;
          return F[j] + (value - X[j]) * b[j] + jStat.sq(value - X[j]) * c[j] + (value - X[j]) * jStat.sq(value - X[j]) * d[j];
        },
        gauss_quadrature: function gauss_quadrature() {
          throw new Error('gauss_quadrature not yet implemented');
        },
        PCA: function PCA(X) {
          var m = X.length;
          var n = X[0].length;
          var flag = false;
          var i = 0;
          var j,
              temp1;
          var u = [];
          var D = [];
          var result = [];
          var temp2 = [];
          var Y = [];
          var Bt = [];
          var B = [];
          var C = [];
          var V = [];
          var Vt = [];
          for (i = 0; i < m; i++) {
            u[i] = jStat.sum(X[i]) / n;
          }
          for (i = 0; i < n; i++) {
            B[i] = [];
            for (j = 0; j < m; j++) {
              B[i][j] = X[j][i] - u[j];
            }
          }
          B = jStat.transpose(B);
          for (i = 0; i < m; i++) {
            C[i] = [];
            for (j = 0; j < m; j++) {
              C[i][j] = (jStat.dot([B[i]], [B[j]])) / (n - 1);
            }
          }
          result = jStat.jacobi(C);
          V = result[0];
          D = result[1];
          Vt = jStat.transpose(V);
          for (i = 0; i < D.length; i++) {
            for (j = i; j < D.length; j++) {
              if (D[i] < D[j]) {
                temp1 = D[i];
                D[i] = D[j];
                D[j] = temp1;
                temp2 = Vt[i];
                Vt[i] = Vt[j];
                Vt[j] = temp2;
              }
            }
          }
          Bt = jStat.transpose(B);
          for (i = 0; i < m; i++) {
            Y[i] = [];
            for (j = 0; j < Bt.length; j++) {
              Y[i][j] = jStat.dot([Vt[i]], [Bt[j]]);
            }
          }
          return [X, D, Vt, Y];
        }
      });
      (function(funcs) {
        for (var i = 0; i < funcs.length; i++)
          (function(passfunc) {
            jStat.fn[passfunc] = function(arg, func) {
              var tmpthis = this;
              if (func) {
                setTimeout(function() {
                  func.call(tmpthis, jStat.fn[passfunc].call(tmpthis, arg));
                }, 15);
                return this;
              }
              if (typeof jStat[passfunc](this, arg) === 'number')
                return jStat[passfunc](this, arg);
              else
                return jStat(jStat[passfunc](this, arg));
            };
          }(funcs[i]));
      }('add divide multiply subtract dot pow exp log abs norm angle'.split(' ')));
    }(this.jStat, Math));
    (function(jStat, Math) {
      var slice = [].slice;
      var isNumber = jStat.utils.isNumber;
      jStat.extend({
        zscore: function zscore() {
          var args = slice.call(arguments);
          if (isNumber(args[1])) {
            return (args[0] - args[1]) / args[2];
          }
          return (args[0] - jStat.mean(args[1])) / jStat.stdev(args[1], args[2]);
        },
        ztest: function ztest() {
          var args = slice.call(arguments);
          if (args.length === 4) {
            if (isNumber(args[1])) {
              var z = jStat.zscore(args[0], args[1], args[2]);
              return (args[3] === 1) ? (jStat.normal.cdf(-Math.abs(z), 0, 1)) : (jStat.normal.cdf(-Math.abs(z), 0, 1) * 2);
            }
            var z = args[0];
            return (args[2] === 1) ? (jStat.normal.cdf(-Math.abs(z), 0, 1)) : (jStat.normal.cdf(-Math.abs(z), 0, 1) * 2);
          }
          var z = jStat.zscore(args[0], args[1], args[3]);
          return (args[1] === 1) ? (jStat.normal.cdf(-Math.abs(z), 0, 1)) : (jStat.normal.cdf(-Math.abs(z), 0, 1) * 2);
        }
      });
      jStat.extend(jStat.fn, {
        zscore: function zscore(value, flag) {
          return (value - this.mean()) / this.stdev(flag);
        },
        ztest: function ztest(value, sides, flag) {
          var zscore = Math.abs(this.zscore(value, flag));
          return (sides === 1) ? (jStat.normal.cdf(-zscore, 0, 1)) : (jStat.normal.cdf(-zscore, 0, 1) * 2);
        }
      });
      jStat.extend({
        tscore: function tscore() {
          var args = slice.call(arguments);
          return (args.length === 4) ? ((args[0] - args[1]) / (args[2] / Math.sqrt(args[3]))) : ((args[0] - jStat.mean(args[1])) / (jStat.stdev(args[1], true) / Math.sqrt(args[1].length)));
        },
        ttest: function ttest() {
          var args = slice.call(arguments);
          var tscore;
          if (args.length === 5) {
            tscore = Math.abs(jStat.tscore(args[0], args[1], args[2], args[3]));
            return (args[4] === 1) ? (jStat.studentt.cdf(-tscore, args[3] - 1)) : (jStat.studentt.cdf(-tscore, args[3] - 1) * 2);
          }
          if (isNumber(args[1])) {
            tscore = Math.abs(args[0]);
            return (args[2] == 1) ? (jStat.studentt.cdf(-tscore, args[1] - 1)) : (jStat.studentt.cdf(-tscore, args[1] - 1) * 2);
          }
          tscore = Math.abs(jStat.tscore(args[0], args[1]));
          return (args[2] == 1) ? (jStat.studentt.cdf(-tscore, args[1].length - 1)) : (jStat.studentt.cdf(-tscore, args[1].length - 1) * 2);
        }
      });
      jStat.extend(jStat.fn, {
        tscore: function tscore(value) {
          return (value - this.mean()) / (this.stdev(true) / Math.sqrt(this.cols()));
        },
        ttest: function ttest(value, sides) {
          return (sides === 1) ? (1 - jStat.studentt.cdf(Math.abs(this.tscore(value)), this.cols() - 1)) : (jStat.studentt.cdf(-Math.abs(this.tscore(value)), this.cols() - 1) * 2);
        }
      });
      jStat.extend({
        anovafscore: function anovafscore() {
          var args = slice.call(arguments),
              expVar,
              sample,
              sampMean,
              sampSampMean,
              tmpargs,
              unexpVar,
              i,
              j;
          if (args.length === 1) {
            tmpargs = new Array(args[0].length);
            for (i = 0; i < args[0].length; i++) {
              tmpargs[i] = args[0][i];
            }
            args = tmpargs;
          }
          if (args.length === 2) {
            return jStat.variance(args[0]) / jStat.variance(args[1]);
          }
          sample = new Array();
          for (i = 0; i < args.length; i++) {
            sample = sample.concat(args[i]);
          }
          sampMean = jStat.mean(sample);
          expVar = 0;
          for (i = 0; i < args.length; i++) {
            expVar = expVar + args[i].length * Math.pow(jStat.mean(args[i]) - sampMean, 2);
          }
          expVar /= (args.length - 1);
          unexpVar = 0;
          for (i = 0; i < args.length; i++) {
            sampSampMean = jStat.mean(args[i]);
            for (j = 0; j < args[i].length; j++) {
              unexpVar += Math.pow(args[i][j] - sampSampMean, 2);
            }
          }
          unexpVar /= (sample.length - args.length);
          return expVar / unexpVar;
        },
        anovaftest: function anovaftest() {
          var args = slice.call(arguments),
              df1,
              df2,
              n,
              i;
          if (isNumber(args[0])) {
            return 1 - jStat.centralF.cdf(args[0], args[1], args[2]);
          }
          anovafscore = jStat.anovafscore(args);
          df1 = args.length - 1;
          n = 0;
          for (i = 0; i < args.length; i++) {
            n = n + args[i].length;
          }
          df2 = n - df1 - 1;
          return 1 - jStat.centralF.cdf(anovafscore, df1, df2);
        },
        ftest: function ftest(fscore, df1, df2) {
          return 1 - jStat.centralF.cdf(fscore, df1, df2);
        }
      });
      jStat.extend(jStat.fn, {
        anovafscore: function anovafscore() {
          return jStat.anovafscore(this.toArray());
        },
        anovaftes: function anovaftes() {
          var n = 0;
          var i;
          for (i = 0; i < this.length; i++) {
            n = n + this[i].length;
          }
          return jStat.ftest(this.anovafscore(), this.length - 1, n - this.length);
        }
      });
      jStat.extend({
        normalci: function normalci() {
          var args = slice.call(arguments),
              ans = new Array(2),
              change;
          if (args.length === 4) {
            change = Math.abs(jStat.normal.inv(args[1] / 2, 0, 1) * args[2] / Math.sqrt(args[3]));
          } else {
            change = Math.abs(jStat.normal.inv(args[1] / 2, 0, 1) * jStat.stdev(args[2]) / Math.sqrt(args[2].length));
          }
          ans[0] = args[0] - change;
          ans[1] = args[0] + change;
          return ans;
        },
        tci: function tci() {
          var args = slice.call(arguments),
              ans = new Array(2),
              change;
          if (args.length === 4) {
            change = Math.abs(jStat.studentt.inv(args[1] / 2, args[3] - 1) * args[2] / Math.sqrt(args[3]));
          } else {
            change = Math.abs(jStat.studentt.inv(args[1] / 2, args[2].length - 1) * jStat.stdev(args[2], true) / Math.sqrt(args[2].length));
          }
          ans[0] = args[0] - change;
          ans[1] = args[0] + change;
          return ans;
        },
        significant: function significant(pvalue, alpha) {
          return pvalue < alpha;
        }
      });
      jStat.extend(jStat.fn, {
        normalci: function normalci(value, alpha) {
          return jStat.normalci(value, alpha, this.toArray());
        },
        tci: function tci(value, alpha) {
          return jStat.tci(value, alpha, this.toArray());
        }
      });
    }(this.jStat, Math));
  })();
  return _retrieveGlobal();
});

$__System.registerDynamic("21", [], false, function($__require, $__exports, $__module) {
  var _retrieveGlobal = $__System.get("@@global-helpers").prepareGlobal($__module.id, null, null);
  (function() {
    this["deepEq$"] = deepEq$;
    var Signal = this["Signal"];
    var out$ = this["out$"];
    var Signal,
        out$ = typeof exports != 'undefined' && exports || this;
    out$.Signal = Signal = function(arg$) {
      var onAdd,
          ref$,
          listeners,
          signal;
      onAdd = (ref$ = (arg$ != null ? arg$ : {}).onAdd) != null ? ref$ : function() {};
      listeners = [];
      signal = function(cb) {
        if (deepEq$(onAdd(cb), false, '===')) {
          return;
        }
        return listeners.push(cb);
      };
      signal.add = signal;
      signal.dispatch = function() {
        var args,
            res$,
            i$,
            to$,
            oldListeners,
            survivors,
            x$,
            len$;
        res$ = [];
        for (i$ = 0, to$ = arguments.length; i$ < to$; ++i$) {
          res$.push(arguments[i$]);
        }
        args = res$;
        oldListeners = listeners;
        listeners = [];
        res$ = [];
        for (i$ = 0, len$ = oldListeners.length; i$ < len$; ++i$) {
          x$ = oldListeners[i$];
          if (!deepEq$(x$.apply(null, args), false, '===')) {
            res$.push(x$);
          }
        }
        survivors = res$;
        listeners = survivors.concat(listeners);
      };
      signal.destroy = function() {
        listeners = [];
        return signal.dispatch = function() {
          return false;
        };
      };
      return signal;
    };
    function deepEq$(x, y, type) {
      var toString = {}.toString,
          hasOwnProperty = {}.hasOwnProperty,
          has = function(obj, key) {
            return hasOwnProperty.call(obj, key);
          };
      var first = true;
      return eq(x, y, []);
      function eq(a, b, stack) {
        var className,
            length,
            size,
            result,
            alength,
            blength,
            r,
            key,
            ref,
            sizeB;
        if (a == null || b == null) {
          return a === b;
        }
        if (a.__placeholder__ || b.__placeholder__) {
          return true;
        }
        if (a === b) {
          return a !== 0 || 1 / a == 1 / b;
        }
        className = toString.call(a);
        if (toString.call(b) != className) {
          return false;
        }
        switch (className) {
          case '[object String]':
            return a == String(b);
          case '[object Number]':
            return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b);
          case '[object Date]':
          case '[object Boolean]':
            return +a == +b;
          case '[object RegExp]':
            return a.source == b.source && a.global == b.global && a.multiline == b.multiline && a.ignoreCase == b.ignoreCase;
        }
        if (typeof a != 'object' || typeof b != 'object') {
          return false;
        }
        length = stack.length;
        while (length--) {
          if (stack[length] == a) {
            return true;
          }
        }
        stack.push(a);
        size = 0;
        result = true;
        if (className == '[object Array]') {
          alength = a.length;
          blength = b.length;
          if (first) {
            switch (type) {
              case '===':
                result = alength === blength;
                break;
              case '<==':
                result = alength <= blength;
                break;
              case '<<=':
                result = alength < blength;
                break;
            }
            size = alength;
            first = false;
          } else {
            result = alength === blength;
            size = alength;
          }
          if (result) {
            while (size--) {
              if (!(result = size in a == size in b && eq(a[size], b[size], stack))) {
                break;
              }
            }
          }
        } else {
          if ('constructor' in a != 'constructor' in b || a.constructor != b.constructor) {
            return false;
          }
          for (key in a) {
            if (has(a, key)) {
              size++;
              if (!(result = has(b, key) && eq(a[key], b[key], stack))) {
                break;
              }
            }
          }
          if (result) {
            sizeB = 0;
            for (key in b) {
              if (has(b, key)) {
                ++sizeB;
              }
            }
            if (first) {
              if (type === '<<=') {
                result = size < sizeB;
              } else if (type === '<==') {
                result = size <= sizeB;
              } else {
                result = size === sizeB;
              }
            } else {
              first = false;
              result = size === sizeB;
            }
          }
        }
        stack.pop();
        return result;
      }
    }
    this["Signal"] = Signal;
    this["out$"] = out$;
  })();
  return _retrieveGlobal();
});

$__System.registerDynamic("37", ["25", "19", "29", "1a", "21"], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  var THREE,
      $,
      jStat,
      seqr,
      Signal,
      AngledThing,
      React,
      SpatialCatch,
      BallisticThing,
      Catchthething,
      out$ = typeof exports != 'undefined' && exports || this;
  THREE = $__require('25');
  $ = $__require('19');
  jStat = $__require('29');
  seqr = $__require('1a');
  Signal = $__require('21').Signal;
  AngledThing = (function() {
    AngledThing.displayName = 'AngledThing';
    var prototype = AngledThing.prototype,
        constructor = AngledThing;
    function AngledThing(arg$) {
      var ref$,
          ref1$,
          objectGeometry,
          objectMaterial,
          this$ = this;
      ref$ = arg$ != null ? arg$ : {}, this.oddballRate = (ref1$ = ref$.oddballRate) != null ? ref1$ : 0, this.angle = ref$.angle, this.totalHeight = (ref1$ = ref$.totalHeight) != null ? ref1$ : 1.0;
      this.rndpos = function() {
        return (Math.random() - 0.5) * this$.totalHeight;
      };
      this.targetY = this.rndpos();
      this.originY = this.rndpos();
      objectGeometry = new THREE.SphereGeometry(0.01, 32, 32);
      objectMaterial = new THREE.MeshBasicMaterial({color: 0xffffff});
      this.mesh = new THREE.Mesh(objectGeometry, objectMaterial);
      this.mesh.position.set(1, 0, 0);
      this.velocity = -1.5;
      this.manipulated = false;
      this.t = 0;
    }
    AngledThing.prototype.tick = function(dt) {
      var prevPos,
          x0,
          x1,
          total,
          d,
          x,
          relx,
          manip;
      this.t += dt;
      prevPos = this.mesh.position.clone();
      x0 = 1;
      x1 = -0.5;
      total = x0 - x1;
      d = Math.abs(this.velocity * this.t);
      this.mesh.position.x = x = this.velocity * this.t + x0;
      relx = d / total;
      this.mesh.position.y = (1 - relx) * this.originY + relx * this.targetY;
      if (prevPos.x > 0 && this.mesh.position.x < 0 && !this.manipulated && Math.random() < this.oddballRate) {
        manip = Math.sign(Math.random() - 0.5) * 0.05;
        console.log(manip);
        this.manipulated = true;
        this.targetY += manip;
        return this.originY += manip;
      }
    };
    return AngledThing;
  }());
  out$.React = React = seqr.bind(function*(arg$) {
    var ref$,
        meanDelay,
        ref1$,
        probeDuration,
        fadeOutDuration,
        self,
        x$,
        camera,
        scene,
        probeRadius,
        probe,
        _readyForNew,
        randcoord;
    ref$ = arg$ != null ? arg$ : {}, meanDelay = (ref1$ = ref$.meanDelay) != null ? ref1$ : 0.5, probeDuration = (ref1$ = ref$.probeDuration) != null ? ref1$ : 1, fadeOutDuration = (ref1$ = ref$.fadeOutDuration) != null ? ref1$ : 0.2;
    self = {};
    self.event = Signal();
    x$ = self.camera = camera = new THREE.OrthographicCamera(-1, 1, -1, 1, 0.1, 10);
    x$.position.z = 5;
    self.scene = scene = new THREE.Scene;
    probeRadius = 0.05;
    probe = new THREE.Mesh(new THREE.SphereGeometry(probeRadius, 32, 32), new THREE.MeshBasicMaterial({
      color: 0xffffff,
      transparent: true
    }));
    probe.visible = false;
    probe.active = false;
    probe.timeLeft = 0;
    probe.fadeLeft = 0;
    self.scene.add(probe);
    self.score = {
      catched: 0,
      missed: 0,
      fumbled: 0
    };
    _readyForNew = function(dt) {
      if (probe.visible) {
        return false;
      }
      return Math.random() > Math.exp(-1 / meanDelay * dt);
    };
    randcoord = function() {
      return (Math.random() - 0.5) * 2 * 0.8;
    };
    self.tick = function(dt) {
      var stage,
          scale;
      if (probe.active) {
        probe.timeLeft -= dt;
        if (probe.timeLeft <= 0) {
          self.score.missed += 1;
          self.event.dispatch("missed");
          probe.visible = false;
          probe.active = false;
        }
      } else if (probe.visible) {
        probe.fadeLeft -= dt;
        if (probe.fadeLeft <= 0) {
          probe.visible = false;
        } else {
          stage = probe.fadeLeft / fadeOutDuration;
          probe.material.opacity = stage;
          scale = Math.min(100, 1.0 / stage);
          probe.scale.set(scale, scale, scale);
        }
      }
      if (_readyForNew(dt)) {
        self.event.dispatch("show");
        probe.material.opacity = 1.0;
        probe.scale.set(1.0, 1.0, 1.0);
        probe.visible = true;
        probe.active = true;
        probe.position.x = randcoord();
        probe.position.y = randcoord();
        return probe.timeLeft = probeDuration;
      }
    };
    self['catch'] = function() {
      if (!probe.active) {
        self.event.dispatch("fumbled");
        self.score.fumbled += 1;
        return;
      }
      self.event.dispatch("caught");
      self.score.catched += 1;
      probe.active = false;
      return probe.fadeLeft = fadeOutDuration;
    };
    return self;
  });
  out$.SpatialCatch = SpatialCatch = (function() {
    SpatialCatch.displayName = 'SpatialCatch';
    var prototype = SpatialCatch.prototype,
        constructor = SpatialCatch;
    function SpatialCatch(arg$) {
      var ref$,
          ref1$,
          x$,
          targetWidth,
          targetHeight,
          maskWidth;
      ref$ = arg$ != null ? arg$ : {}, this.oddballRate = (ref1$ = ref$.oddballRate) != null ? ref1$ : 0.0, this.controls = ref$.controls;
      this.objectHandled = Signal();
      this.objectCatched = Signal();
      this.objectMissed = Signal();
      this.objectAdded = Signal();
      x$ = this.camera = new THREE.OrthographicCamera(-1, 1, -1, 1, 0.1, 10);
      x$.position.z = 5;
      this.camera.updateProjectionMatrix();
      this.camera.updateMatrixWorld();
      this.camera.matrixWorldInverse.getInverse(this.camera.matrixWorld);
      this.frustum = new THREE.Frustum;
      this.frustum.setFromMatrix(new THREE.Matrix4().multiplyMatrices(this.camera.projectionMatrix, this.camera.matrixWorldInverse));
      this.scene = new THREE.Scene;
      targetWidth = 0.03;
      targetHeight = this.targetHeight = 0.5;
      this.targetX = -0.5;
      this.inactiveOpacity = 0.3;
      this.activeOpacity = 1.0;
      this.topTarget = new THREE.Mesh(new THREE.PlaneGeometry(targetWidth, targetHeight), new THREE.MeshBasicMaterial({
        color: 0x8B0000,
        opacity: this.inactiveOpacity,
        transparent: true
      }));
      this.topTarget.rotation.y = -Math.PI;
      this.topTarget.position.y = -targetHeight / 2.0;
      this.topTarget.position.x = this.targetX;
      this.scene.add(this.topTarget);
      this.bottomTarget = new THREE.Mesh(new THREE.PlaneGeometry(targetWidth, targetHeight), new THREE.MeshBasicMaterial({
        color: 0x00008B,
        opacity: this.inactiveOpacity,
        transparent: true
      }));
      this.bottomTarget.rotation.y = -Math.PI;
      this.bottomTarget.position.y = targetHeight / 2.0;
      this.bottomTarget.position.x = this.targetX;
      this.scene.add(this.bottomTarget);
      maskWidth = 0.3;
      this.mask = new THREE.Mesh(new THREE.PlaneGeometry(maskWidth, targetHeight * 2), new THREE.MeshBasicMaterial({color: 0x000000}));
      this.mask.rotation.y = -Math.PI;
      this.scene.add(this.mask);
      this.meanDelay = 0.5;
      this.objects = [];
      this._objCount = 0;
      this.t = 0;
      this.prevBall = 0;
    }
    SpatialCatch.prototype._readyForNew = function(dt) {
      if (this.objects.length > 0) {
        return false;
      }
      return this.t - this.prevBall > this.meanDelay;
    };
    SpatialCatch.prototype.tick = function(dt) {
      var thing,
          prev,
          i$,
          len$,
          prevX,
          y,
          caught,
          results$ = [];
      this.t += dt;
      if (this._readyForNew(dt)) {
        thing = new AngledThing({
          oddballRate: this.oddballRate,
          totalHeight: 0.3
        });
        thing.id = this._objCount;
        this._objCount += 1;
        this.scene.add(thing.mesh);
        this.objectAdded.dispatch(thing);
        this.objects.push(thing);
      }
      this.topTarget.material.opacity = this.inactiveOpacity;
      this.bottomTarget.material.opacity = this.inactiveOpacity;
      if (this.controls.up && !this.controls.down) {
        this.topTarget.material.opacity = this.activeOpacity;
      }
      if (this.controls.down && !this.controls.up) {
        this.bottomTarget.material.opacity = this.activeOpacity;
      }
      prev = this.objects;
      this.objects = [];
      for (i$ = 0, len$ = prev.length; i$ < len$; ++i$) {
        thing = prev[i$];
        prevX = thing.mesh.position.x;
        thing.tick(dt);
        if (prevX > this.targetX && thing.mesh.position.x < this.targetX) {
          y = thing.mesh.position.y;
          caught = y < 0 && this.controls.up;
          caught = caught || y > 0 && this.controls.down;
          caught = caught && !(this.controls.up && this.controls.down);
          if (caught) {
            this.objectHandled.dispatch(thing);
            this.objectCatched.dispatch(thing);
            this.scene.remove(thing.mesh);
            this.prevBall = this.t;
            continue;
          }
        }
        if (!this.frustum.containsPoint(thing.mesh.position)) {
          this.scene.remove(thing.mesh);
          this.objectMissed.dispatch(thing);
          this.objectHandled.dispatch(thing);
          this.prevBall = this.t;
          continue;
        }
        results$.push(this.objects.push(thing));
      }
      return results$;
    };
    return SpatialCatch;
  }());
  BallisticThing = (function() {
    BallisticThing.displayName = 'BallisticThing';
    var prototype = BallisticThing.prototype,
        constructor = BallisticThing;
    function BallisticThing(arg$) {
      var ref$,
          objectGeometry,
          objectMaterial;
      this.oddballRate = (ref$ = (arg$ != null ? arg$ : {}).oddballRate) != null ? ref$ : 0;
      objectGeometry = new THREE.SphereGeometry(0.01, 32, 32);
      objectMaterial = new THREE.MeshBasicMaterial({color: 0xffffff});
      this.mesh = new THREE.Mesh(objectGeometry, objectMaterial);
      this.mesh.position.set(1, 0, 0);
      this.velocity = -1.5;
      this.manipulated = false;
      this.t = 0;
    }
    BallisticThing.prototype.tick = function(dt) {
      var prevPos,
          x0,
          x1,
          x,
          total,
          h,
          y0,
          d,
          a,
          b,
          manip;
      this.t += dt;
      prevPos = this.mesh.position.clone();
      x0 = 1;
      x1 = -0.5;
      this.mesh.position.x = x = this.velocity * this.t + x0;
      total = x0 - x1;
      h = -0.3;
      y0 = 0;
      d = Math.abs(this.velocity * this.t);
      a = -4 * (h - y0) / Math.pow(total, 2);
      b = 4 * (h - y0) / total;
      this.mesh.position.y = y0 + a * Math.pow(d, 2) + b * d;
      if (prevPos.x > 0 && this.mesh.position.x < 0 && !this.manipulated && Math.random() < this.oddballRate) {
        manip = Math.sign((Math.random() - 0.5) * 2) * 0.1;
        this.t += manip;
        return this.manipulated = true;
      }
    };
    return BallisticThing;
  }());
  out$.Catchthething = Catchthething = (function() {
    Catchthething.displayName = 'Catchthething';
    var prototype = Catchthething.prototype,
        constructor = Catchthething;
    function Catchthething(arg$) {
      var ref$,
          x$,
          radius,
          targetGeo,
          targetMaterial,
          targetMesh,
          mask;
      this.oddballRate = (ref$ = (arg$ != null ? arg$ : {}).oddballRate) != null ? ref$ : 0;
      this.objectHandled = Signal();
      this.objectCatched = Signal();
      this.objectMissed = Signal();
      x$ = this.camera = new THREE.OrthographicCamera(-1, 1, -1, 1, 0.1, 10);
      x$.position.z = 5;
      this.camera.updateProjectionMatrix();
      this.camera.updateMatrixWorld();
      this.camera.matrixWorldInverse.getInverse(this.camera.matrixWorld);
      this.frustum = new THREE.Frustum;
      this.frustum.setFromMatrix(new THREE.Matrix4().multiplyMatrices(this.camera.projectionMatrix, this.camera.matrixWorldInverse));
      this.scene = new THREE.Scene;
      radius = 0.15;
      this.target = new THREE.Sphere(new THREE.Vector3(0, 0, 0), radius);
      this.objects = [];
      targetGeo = new THREE.SphereGeometry(this.target.radius, 32, 32);
      targetMaterial = new THREE.MeshBasicMaterial({
        color: 0xffffff,
        wireframe: true
      });
      targetMesh = new THREE.Mesh(targetGeo, targetMaterial);
      this.scene.add(targetMesh);
      this.targetMesh = targetMesh;
      this.targetMesh.position.x = -0.5;
      mask = new THREE.Mesh(new THREE.PlaneGeometry(0.3, 0.3), new THREE.MeshBasicMaterial({color: 0xffffff}));
      mask.position.z = -1;
      mask.position.y = -0.3;
      mask.rotation.x = Math.PI;
      this.scene.add(mask);
      this.meanDelay = 1;
    }
    Catchthething.prototype._readyForNew = function(dt) {
      if (this.objects.length > 0) {
        return false;
      }
      return Math.random() > Math.exp(-1 / this.meanDelay * dt);
    };
    Catchthething.prototype.resize = function(w, h) {};
    Catchthething.prototype.tick = function(dt) {
      var thing,
          prev,
          i$,
          len$,
          results$ = [];
      if (this._readyForNew(dt)) {
        thing = new BallisticThing({oddballRate: this.oddballRate});
        this.scene.add(thing.mesh);
        this.objects.push(thing);
      }
      prev = this.objects;
      this.objects = [];
      for (i$ = 0, len$ = prev.length; i$ < len$; ++i$) {
        thing = prev[i$];
        thing.tick(dt);
        if (!this.frustum.containsPoint(thing.mesh.position)) {
          this.scene.remove(thing.mesh);
          this.objectHandled.dispatch(thing);
          this.objectMissed.dispatch(thing);
          continue;
        }
        results$.push(this.objects.push(thing));
      }
      return results$;
    };
    Catchthething.prototype['catch'] = function() {
      var misses,
          i$,
          ref$,
          len$,
          obj,
          d;
      misses = [];
      for (i$ = 0, len$ = (ref$ = this.objects).length; i$ < len$; ++i$) {
        obj = ref$[i$];
        d = this.targetMesh.position.distanceTo(obj.mesh.position);
        if (d >= this.target.radius) {
          misses.push(obj);
          continue;
        }
        this.scene.remove(obj.mesh);
        this.objectHandled.dispatch(obj);
        this.objectCatched.dispatch(obj);
      }
      return this.objects = misses;
    };
    return Catchthething;
  }());
  return module.exports;
});

$__System.registerDynamic("38", [], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  var apply,
      curry,
      flip,
      fix,
      over,
      memoize,
      slice$ = [].slice,
      toString$ = {}.toString;
  apply = curry$(function(f, list) {
    return f.apply(null, list);
  });
  curry = function(f) {
    return curry$(f);
  };
  flip = curry$(function(f, x, y) {
    return f(y, x);
  });
  fix = function(f) {
    return function(g) {
      return function() {
        return f(g(g)).apply(null, arguments);
      };
    }(function(g) {
      return function() {
        return f(g(g)).apply(null, arguments);
      };
    });
  };
  over = curry$(function(f, g, x, y) {
    return f(g(x), g(y));
  });
  memoize = function(f) {
    var memo;
    memo = {};
    return function() {
      var args,
          key,
          arg;
      args = slice$.call(arguments);
      key = (function() {
        var i$,
            ref$,
            len$,
            results$ = [];
        for (i$ = 0, len$ = (ref$ = args).length; i$ < len$; ++i$) {
          arg = ref$[i$];
          results$.push(arg + toString$.call(arg).slice(8, -1));
        }
        return results$;
      }()).join('');
      return memo[key] = key in memo ? memo[key] : f.apply(null, args);
    };
  };
  module.exports = {
    curry: curry,
    flip: flip,
    fix: fix,
    apply: apply,
    over: over,
    memoize: memoize
  };
  function curry$(f, bound) {
    var context,
        _curry = function(args) {
          return f.length > 1 ? function() {
            var params = args ? args.concat() : [];
            context = bound ? context || this : this;
            return params.push.apply(params, arguments) < f.length && arguments.length ? _curry.call(context, params) : f.apply(context, params);
          } : f;
        };
    return _curry();
  }
  return module.exports;
});

$__System.registerDynamic("39", [], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  var each,
      map,
      compact,
      filter,
      reject,
      partition,
      find,
      head,
      first,
      tail,
      last,
      initial,
      empty,
      reverse,
      unique,
      uniqueBy,
      fold,
      foldl,
      fold1,
      foldl1,
      foldr,
      foldr1,
      unfoldr,
      concat,
      concatMap,
      flatten,
      difference,
      intersection,
      union,
      countBy,
      groupBy,
      andList,
      orList,
      any,
      all,
      sort,
      sortWith,
      sortBy,
      sum,
      product,
      mean,
      average,
      maximum,
      minimum,
      maximumBy,
      minimumBy,
      scan,
      scanl,
      scan1,
      scanl1,
      scanr,
      scanr1,
      slice,
      take,
      drop,
      splitAt,
      takeWhile,
      dropWhile,
      span,
      breakList,
      zip,
      zipWith,
      zipAll,
      zipAllWith,
      at,
      elemIndex,
      elemIndices,
      findIndex,
      findIndices,
      toString$ = {}.toString,
      slice$ = [].slice;
  each = curry$(function(f, xs) {
    var i$,
        len$,
        x;
    for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
      x = xs[i$];
      f(x);
    }
    return xs;
  });
  map = curry$(function(f, xs) {
    var i$,
        len$,
        x,
        results$ = [];
    for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
      x = xs[i$];
      results$.push(f(x));
    }
    return results$;
  });
  compact = function(xs) {
    var i$,
        len$,
        x,
        results$ = [];
    for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
      x = xs[i$];
      if (x) {
        results$.push(x);
      }
    }
    return results$;
  };
  filter = curry$(function(f, xs) {
    var i$,
        len$,
        x,
        results$ = [];
    for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
      x = xs[i$];
      if (f(x)) {
        results$.push(x);
      }
    }
    return results$;
  });
  reject = curry$(function(f, xs) {
    var i$,
        len$,
        x,
        results$ = [];
    for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
      x = xs[i$];
      if (!f(x)) {
        results$.push(x);
      }
    }
    return results$;
  });
  partition = curry$(function(f, xs) {
    var passed,
        failed,
        i$,
        len$,
        x;
    passed = [];
    failed = [];
    for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
      x = xs[i$];
      (f(x) ? passed : failed).push(x);
    }
    return [passed, failed];
  });
  find = curry$(function(f, xs) {
    var i$,
        len$,
        x;
    for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
      x = xs[i$];
      if (f(x)) {
        return x;
      }
    }
  });
  head = first = function(xs) {
    return xs[0];
  };
  tail = function(xs) {
    if (!xs.length) {
      return;
    }
    return xs.slice(1);
  };
  last = function(xs) {
    return xs[xs.length - 1];
  };
  initial = function(xs) {
    if (!xs.length) {
      return;
    }
    return xs.slice(0, -1);
  };
  empty = function(xs) {
    return !xs.length;
  };
  reverse = function(xs) {
    return xs.concat().reverse();
  };
  unique = function(xs) {
    var result,
        i$,
        len$,
        x;
    result = [];
    for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
      x = xs[i$];
      if (!in$(x, result)) {
        result.push(x);
      }
    }
    return result;
  };
  uniqueBy = curry$(function(f, xs) {
    var seen,
        i$,
        len$,
        x,
        val,
        results$ = [];
    seen = [];
    for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
      x = xs[i$];
      val = f(x);
      if (in$(val, seen)) {
        continue;
      }
      seen.push(val);
      results$.push(x);
    }
    return results$;
  });
  fold = foldl = curry$(function(f, memo, xs) {
    var i$,
        len$,
        x;
    for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
      x = xs[i$];
      memo = f(memo, x);
    }
    return memo;
  });
  fold1 = foldl1 = curry$(function(f, xs) {
    return fold(f, xs[0], xs.slice(1));
  });
  foldr = curry$(function(f, memo, xs) {
    var i$,
        x;
    for (i$ = xs.length - 1; i$ >= 0; --i$) {
      x = xs[i$];
      memo = f(x, memo);
    }
    return memo;
  });
  foldr1 = curry$(function(f, xs) {
    return foldr(f, xs[xs.length - 1], xs.slice(0, -1));
  });
  unfoldr = curry$(function(f, b) {
    var result,
        x,
        that;
    result = [];
    x = b;
    while ((that = f(x)) != null) {
      result.push(that[0]);
      x = that[1];
    }
    return result;
  });
  concat = function(xss) {
    return [].concat.apply([], xss);
  };
  concatMap = curry$(function(f, xs) {
    var x;
    return [].concat.apply([], (function() {
      var i$,
          ref$,
          len$,
          results$ = [];
      for (i$ = 0, len$ = (ref$ = xs).length; i$ < len$; ++i$) {
        x = ref$[i$];
        results$.push(f(x));
      }
      return results$;
    }()));
  });
  flatten = function(xs) {
    var x;
    return [].concat.apply([], (function() {
      var i$,
          ref$,
          len$,
          results$ = [];
      for (i$ = 0, len$ = (ref$ = xs).length; i$ < len$; ++i$) {
        x = ref$[i$];
        if (toString$.call(x).slice(8, -1) === 'Array') {
          results$.push(flatten(x));
        } else {
          results$.push(x);
        }
      }
      return results$;
    }()));
  };
  difference = function(xs) {
    var yss,
        results,
        i$,
        len$,
        x,
        j$,
        len1$,
        ys;
    yss = slice$.call(arguments, 1);
    results = [];
    outer: for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
      x = xs[i$];
      for (j$ = 0, len1$ = yss.length; j$ < len1$; ++j$) {
        ys = yss[j$];
        if (in$(x, ys)) {
          continue outer;
        }
      }
      results.push(x);
    }
    return results;
  };
  intersection = function(xs) {
    var yss,
        results,
        i$,
        len$,
        x,
        j$,
        len1$,
        ys;
    yss = slice$.call(arguments, 1);
    results = [];
    outer: for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
      x = xs[i$];
      for (j$ = 0, len1$ = yss.length; j$ < len1$; ++j$) {
        ys = yss[j$];
        if (!in$(x, ys)) {
          continue outer;
        }
      }
      results.push(x);
    }
    return results;
  };
  union = function() {
    var xss,
        results,
        i$,
        len$,
        xs,
        j$,
        len1$,
        x;
    xss = slice$.call(arguments);
    results = [];
    for (i$ = 0, len$ = xss.length; i$ < len$; ++i$) {
      xs = xss[i$];
      for (j$ = 0, len1$ = xs.length; j$ < len1$; ++j$) {
        x = xs[j$];
        if (!in$(x, results)) {
          results.push(x);
        }
      }
    }
    return results;
  };
  countBy = curry$(function(f, xs) {
    var results,
        i$,
        len$,
        x,
        key;
    results = {};
    for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
      x = xs[i$];
      key = f(x);
      if (key in results) {
        results[key] += 1;
      } else {
        results[key] = 1;
      }
    }
    return results;
  });
  groupBy = curry$(function(f, xs) {
    var results,
        i$,
        len$,
        x,
        key;
    results = {};
    for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
      x = xs[i$];
      key = f(x);
      if (key in results) {
        results[key].push(x);
      } else {
        results[key] = [x];
      }
    }
    return results;
  });
  andList = function(xs) {
    var i$,
        len$,
        x;
    for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
      x = xs[i$];
      if (!x) {
        return false;
      }
    }
    return true;
  };
  orList = function(xs) {
    var i$,
        len$,
        x;
    for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
      x = xs[i$];
      if (x) {
        return true;
      }
    }
    return false;
  };
  any = curry$(function(f, xs) {
    var i$,
        len$,
        x;
    for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
      x = xs[i$];
      if (f(x)) {
        return true;
      }
    }
    return false;
  });
  all = curry$(function(f, xs) {
    var i$,
        len$,
        x;
    for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
      x = xs[i$];
      if (!f(x)) {
        return false;
      }
    }
    return true;
  });
  sort = function(xs) {
    return xs.concat().sort(function(x, y) {
      if (x > y) {
        return 1;
      } else if (x < y) {
        return -1;
      } else {
        return 0;
      }
    });
  };
  sortWith = curry$(function(f, xs) {
    return xs.concat().sort(f);
  });
  sortBy = curry$(function(f, xs) {
    return xs.concat().sort(function(x, y) {
      if (f(x) > f(y)) {
        return 1;
      } else if (f(x) < f(y)) {
        return -1;
      } else {
        return 0;
      }
    });
  });
  sum = function(xs) {
    var result,
        i$,
        len$,
        x;
    result = 0;
    for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
      x = xs[i$];
      result += x;
    }
    return result;
  };
  product = function(xs) {
    var result,
        i$,
        len$,
        x;
    result = 1;
    for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
      x = xs[i$];
      result *= x;
    }
    return result;
  };
  mean = average = function(xs) {
    var sum,
        i$,
        len$,
        x;
    sum = 0;
    for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
      x = xs[i$];
      sum += x;
    }
    return sum / xs.length;
  };
  maximum = function(xs) {
    var max,
        i$,
        ref$,
        len$,
        x;
    max = xs[0];
    for (i$ = 0, len$ = (ref$ = xs.slice(1)).length; i$ < len$; ++i$) {
      x = ref$[i$];
      if (x > max) {
        max = x;
      }
    }
    return max;
  };
  minimum = function(xs) {
    var min,
        i$,
        ref$,
        len$,
        x;
    min = xs[0];
    for (i$ = 0, len$ = (ref$ = xs.slice(1)).length; i$ < len$; ++i$) {
      x = ref$[i$];
      if (x < min) {
        min = x;
      }
    }
    return min;
  };
  maximumBy = curry$(function(f, xs) {
    var max,
        i$,
        ref$,
        len$,
        x;
    max = xs[0];
    for (i$ = 0, len$ = (ref$ = xs.slice(1)).length; i$ < len$; ++i$) {
      x = ref$[i$];
      if (f(x) > f(max)) {
        max = x;
      }
    }
    return max;
  });
  minimumBy = curry$(function(f, xs) {
    var min,
        i$,
        ref$,
        len$,
        x;
    min = xs[0];
    for (i$ = 0, len$ = (ref$ = xs.slice(1)).length; i$ < len$; ++i$) {
      x = ref$[i$];
      if (f(x) < f(min)) {
        min = x;
      }
    }
    return min;
  });
  scan = scanl = curry$(function(f, memo, xs) {
    var last,
        x;
    last = memo;
    return [memo].concat((function() {
      var i$,
          ref$,
          len$,
          results$ = [];
      for (i$ = 0, len$ = (ref$ = xs).length; i$ < len$; ++i$) {
        x = ref$[i$];
        results$.push(last = f(last, x));
      }
      return results$;
    }()));
  });
  scan1 = scanl1 = curry$(function(f, xs) {
    if (!xs.length) {
      return;
    }
    return scan(f, xs[0], xs.slice(1));
  });
  scanr = curry$(function(f, memo, xs) {
    xs = xs.concat().reverse();
    return scan(f, memo, xs).reverse();
  });
  scanr1 = curry$(function(f, xs) {
    if (!xs.length) {
      return;
    }
    xs = xs.concat().reverse();
    return scan(f, xs[0], xs.slice(1)).reverse();
  });
  slice = curry$(function(x, y, xs) {
    return xs.slice(x, y);
  });
  take = curry$(function(n, xs) {
    if (n <= 0) {
      return xs.slice(0, 0);
    } else {
      return xs.slice(0, n);
    }
  });
  drop = curry$(function(n, xs) {
    if (n <= 0) {
      return xs;
    } else {
      return xs.slice(n);
    }
  });
  splitAt = curry$(function(n, xs) {
    return [take(n, xs), drop(n, xs)];
  });
  takeWhile = curry$(function(p, xs) {
    var len,
        i;
    len = xs.length;
    if (!len) {
      return xs;
    }
    i = 0;
    while (i < len && p(xs[i])) {
      i += 1;
    }
    return xs.slice(0, i);
  });
  dropWhile = curry$(function(p, xs) {
    var len,
        i;
    len = xs.length;
    if (!len) {
      return xs;
    }
    i = 0;
    while (i < len && p(xs[i])) {
      i += 1;
    }
    return xs.slice(i);
  });
  span = curry$(function(p, xs) {
    return [takeWhile(p, xs), dropWhile(p, xs)];
  });
  breakList = curry$(function(p, xs) {
    return span(compose$(p, not$), xs);
  });
  zip = curry$(function(xs, ys) {
    var result,
        len,
        i$,
        len$,
        i,
        x;
    result = [];
    len = ys.length;
    for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
      i = i$;
      x = xs[i$];
      if (i === len) {
        break;
      }
      result.push([x, ys[i]]);
    }
    return result;
  });
  zipWith = curry$(function(f, xs, ys) {
    var result,
        len,
        i$,
        len$,
        i,
        x;
    result = [];
    len = ys.length;
    for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
      i = i$;
      x = xs[i$];
      if (i === len) {
        break;
      }
      result.push(f(x, ys[i]));
    }
    return result;
  });
  zipAll = function() {
    var xss,
        minLength,
        i$,
        len$,
        xs,
        ref$,
        i,
        lresult$,
        j$,
        results$ = [];
    xss = slice$.call(arguments);
    minLength = undefined;
    for (i$ = 0, len$ = xss.length; i$ < len$; ++i$) {
      xs = xss[i$];
      minLength <= (ref$ = xs.length) || (minLength = ref$);
    }
    for (i$ = 0; i$ < minLength; ++i$) {
      i = i$;
      lresult$ = [];
      for (j$ = 0, len$ = xss.length; j$ < len$; ++j$) {
        xs = xss[j$];
        lresult$.push(xs[i]);
      }
      results$.push(lresult$);
    }
    return results$;
  };
  zipAllWith = function(f) {
    var xss,
        minLength,
        i$,
        len$,
        xs,
        ref$,
        i,
        results$ = [];
    xss = slice$.call(arguments, 1);
    minLength = undefined;
    for (i$ = 0, len$ = xss.length; i$ < len$; ++i$) {
      xs = xss[i$];
      minLength <= (ref$ = xs.length) || (minLength = ref$);
    }
    for (i$ = 0; i$ < minLength; ++i$) {
      i = i$;
      results$.push(f.apply(null, (fn$())));
    }
    return results$;
    function fn$() {
      var i$,
          ref$,
          len$,
          results$ = [];
      for (i$ = 0, len$ = (ref$ = xss).length; i$ < len$; ++i$) {
        xs = ref$[i$];
        results$.push(xs[i]);
      }
      return results$;
    }
  };
  at = curry$(function(n, xs) {
    if (n < 0) {
      return xs[xs.length + n];
    } else {
      return xs[n];
    }
  });
  elemIndex = curry$(function(el, xs) {
    var i$,
        len$,
        i,
        x;
    for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
      i = i$;
      x = xs[i$];
      if (x === el) {
        return i;
      }
    }
  });
  elemIndices = curry$(function(el, xs) {
    var i$,
        len$,
        i,
        x,
        results$ = [];
    for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
      i = i$;
      x = xs[i$];
      if (x === el) {
        results$.push(i);
      }
    }
    return results$;
  });
  findIndex = curry$(function(f, xs) {
    var i$,
        len$,
        i,
        x;
    for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
      i = i$;
      x = xs[i$];
      if (f(x)) {
        return i;
      }
    }
  });
  findIndices = curry$(function(f, xs) {
    var i$,
        len$,
        i,
        x,
        results$ = [];
    for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
      i = i$;
      x = xs[i$];
      if (f(x)) {
        results$.push(i);
      }
    }
    return results$;
  });
  module.exports = {
    each: each,
    map: map,
    filter: filter,
    compact: compact,
    reject: reject,
    partition: partition,
    find: find,
    head: head,
    first: first,
    tail: tail,
    last: last,
    initial: initial,
    empty: empty,
    reverse: reverse,
    difference: difference,
    intersection: intersection,
    union: union,
    countBy: countBy,
    groupBy: groupBy,
    fold: fold,
    fold1: fold1,
    foldl: foldl,
    foldl1: foldl1,
    foldr: foldr,
    foldr1: foldr1,
    unfoldr: unfoldr,
    andList: andList,
    orList: orList,
    any: any,
    all: all,
    unique: unique,
    uniqueBy: uniqueBy,
    sort: sort,
    sortWith: sortWith,
    sortBy: sortBy,
    sum: sum,
    product: product,
    mean: mean,
    average: average,
    concat: concat,
    concatMap: concatMap,
    flatten: flatten,
    maximum: maximum,
    minimum: minimum,
    maximumBy: maximumBy,
    minimumBy: minimumBy,
    scan: scan,
    scan1: scan1,
    scanl: scanl,
    scanl1: scanl1,
    scanr: scanr,
    scanr1: scanr1,
    slice: slice,
    take: take,
    drop: drop,
    splitAt: splitAt,
    takeWhile: takeWhile,
    dropWhile: dropWhile,
    span: span,
    breakList: breakList,
    zip: zip,
    zipWith: zipWith,
    zipAll: zipAll,
    zipAllWith: zipAllWith,
    at: at,
    elemIndex: elemIndex,
    elemIndices: elemIndices,
    findIndex: findIndex,
    findIndices: findIndices
  };
  function curry$(f, bound) {
    var context,
        _curry = function(args) {
          return f.length > 1 ? function() {
            var params = args ? args.concat() : [];
            context = bound ? context || this : this;
            return params.push.apply(params, arguments) < f.length && arguments.length ? _curry.call(context, params) : f.apply(context, params);
          } : f;
        };
    return _curry();
  }
  function in$(x, xs) {
    var i = -1,
        l = xs.length >>> 0;
    while (++i < l)
      if (x === xs[i])
        return true;
    return false;
  }
  function compose$() {
    var functions = arguments;
    return function() {
      var i,
          result;
      result = functions[0].apply(this, arguments);
      for (i = 1; i < functions.length; ++i) {
        result = functions[i](result);
      }
      return result;
    };
  }
  function not$(x) {
    return !x;
  }
  return module.exports;
});

$__System.registerDynamic("3a", [], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  var values,
      keys,
      pairsToObj,
      objToPairs,
      listsToObj,
      objToLists,
      empty,
      each,
      map,
      compact,
      filter,
      reject,
      partition,
      find;
  values = function(object) {
    var i$,
        x,
        results$ = [];
    for (i$ in object) {
      x = object[i$];
      results$.push(x);
    }
    return results$;
  };
  keys = function(object) {
    var x,
        results$ = [];
    for (x in object) {
      results$.push(x);
    }
    return results$;
  };
  pairsToObj = function(object) {
    var i$,
        len$,
        x,
        resultObj$ = {};
    for (i$ = 0, len$ = object.length; i$ < len$; ++i$) {
      x = object[i$];
      resultObj$[x[0]] = x[1];
    }
    return resultObj$;
  };
  objToPairs = function(object) {
    var key,
        value,
        results$ = [];
    for (key in object) {
      value = object[key];
      results$.push([key, value]);
    }
    return results$;
  };
  listsToObj = curry$(function(keys, values) {
    var i$,
        len$,
        i,
        key,
        resultObj$ = {};
    for (i$ = 0, len$ = keys.length; i$ < len$; ++i$) {
      i = i$;
      key = keys[i$];
      resultObj$[key] = values[i];
    }
    return resultObj$;
  });
  objToLists = function(object) {
    var keys,
        values,
        key,
        value;
    keys = [];
    values = [];
    for (key in object) {
      value = object[key];
      keys.push(key);
      values.push(value);
    }
    return [keys, values];
  };
  empty = function(object) {
    var x;
    for (x in object) {
      return false;
    }
    return true;
  };
  each = curry$(function(f, object) {
    var i$,
        x;
    for (i$ in object) {
      x = object[i$];
      f(x);
    }
    return object;
  });
  map = curry$(function(f, object) {
    var k,
        x,
        resultObj$ = {};
    for (k in object) {
      x = object[k];
      resultObj$[k] = f(x);
    }
    return resultObj$;
  });
  compact = function(object) {
    var k,
        x,
        resultObj$ = {};
    for (k in object) {
      x = object[k];
      if (x) {
        resultObj$[k] = x;
      }
    }
    return resultObj$;
  };
  filter = curry$(function(f, object) {
    var k,
        x,
        resultObj$ = {};
    for (k in object) {
      x = object[k];
      if (f(x)) {
        resultObj$[k] = x;
      }
    }
    return resultObj$;
  });
  reject = curry$(function(f, object) {
    var k,
        x,
        resultObj$ = {};
    for (k in object) {
      x = object[k];
      if (!f(x)) {
        resultObj$[k] = x;
      }
    }
    return resultObj$;
  });
  partition = curry$(function(f, object) {
    var passed,
        failed,
        k,
        x;
    passed = {};
    failed = {};
    for (k in object) {
      x = object[k];
      (f(x) ? passed : failed)[k] = x;
    }
    return [passed, failed];
  });
  find = curry$(function(f, object) {
    var i$,
        x;
    for (i$ in object) {
      x = object[i$];
      if (f(x)) {
        return x;
      }
    }
  });
  module.exports = {
    values: values,
    keys: keys,
    pairsToObj: pairsToObj,
    objToPairs: objToPairs,
    listsToObj: listsToObj,
    objToLists: objToLists,
    empty: empty,
    each: each,
    map: map,
    filter: filter,
    compact: compact,
    reject: reject,
    partition: partition,
    find: find
  };
  function curry$(f, bound) {
    var context,
        _curry = function(args) {
          return f.length > 1 ? function() {
            var params = args ? args.concat() : [];
            context = bound ? context || this : this;
            return params.push.apply(params, arguments) < f.length && arguments.length ? _curry.call(context, params) : f.apply(context, params);
          } : f;
        };
    return _curry();
  }
  return module.exports;
});

$__System.registerDynamic("3b", [], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  var split,
      join,
      lines,
      unlines,
      words,
      unwords,
      chars,
      unchars,
      reverse,
      repeat,
      capitalize,
      camelize,
      dasherize;
  split = curry$(function(sep, str) {
    return str.split(sep);
  });
  join = curry$(function(sep, xs) {
    return xs.join(sep);
  });
  lines = function(str) {
    if (!str.length) {
      return [];
    }
    return str.split('\n');
  };
  unlines = function(it) {
    return it.join('\n');
  };
  words = function(str) {
    if (!str.length) {
      return [];
    }
    return str.split(/[ ]+/);
  };
  unwords = function(it) {
    return it.join(' ');
  };
  chars = function(it) {
    return it.split('');
  };
  unchars = function(it) {
    return it.join('');
  };
  reverse = function(str) {
    return str.split('').reverse().join('');
  };
  repeat = curry$(function(n, str) {
    var result,
        i$;
    result = '';
    for (i$ = 0; i$ < n; ++i$) {
      result += str;
    }
    return result;
  });
  capitalize = function(str) {
    return str.charAt(0).toUpperCase() + str.slice(1);
  };
  camelize = function(it) {
    return it.replace(/[-_]+(.)?/g, function(arg$, c) {
      return (c != null ? c : '').toUpperCase();
    });
  };
  dasherize = function(str) {
    return str.replace(/([^-A-Z])([A-Z]+)/g, function(arg$, lower, upper) {
      return lower + "-" + (upper.length > 1 ? upper : upper.toLowerCase());
    }).replace(/^([A-Z]+)/, function(arg$, upper) {
      if (upper.length > 1) {
        return upper + "-";
      } else {
        return upper.toLowerCase();
      }
    });
  };
  module.exports = {
    split: split,
    join: join,
    lines: lines,
    unlines: unlines,
    words: words,
    unwords: unwords,
    chars: chars,
    unchars: unchars,
    reverse: reverse,
    repeat: repeat,
    capitalize: capitalize,
    camelize: camelize,
    dasherize: dasherize
  };
  function curry$(f, bound) {
    var context,
        _curry = function(args) {
          return f.length > 1 ? function() {
            var params = args ? args.concat() : [];
            context = bound ? context || this : this;
            return params.push.apply(params, arguments) < f.length && arguments.length ? _curry.call(context, params) : f.apply(context, params);
          } : f;
        };
    return _curry();
  }
  return module.exports;
});

$__System.registerDynamic("3c", [], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  var max,
      min,
      negate,
      abs,
      signum,
      quot,
      rem,
      div,
      mod,
      recip,
      pi,
      tau,
      exp,
      sqrt,
      ln,
      pow,
      sin,
      tan,
      cos,
      asin,
      acos,
      atan,
      atan2,
      truncate,
      round,
      ceiling,
      floor,
      isItNaN,
      even,
      odd,
      gcd,
      lcm;
  max = curry$(function(x$, y$) {
    return x$ > y$ ? x$ : y$;
  });
  min = curry$(function(x$, y$) {
    return x$ < y$ ? x$ : y$;
  });
  negate = function(x) {
    return -x;
  };
  abs = Math.abs;
  signum = function(x) {
    if (x < 0) {
      return -1;
    } else if (x > 0) {
      return 1;
    } else {
      return 0;
    }
  };
  quot = curry$(function(x, y) {
    return ~~(x / y);
  });
  rem = curry$(function(x$, y$) {
    return x$ % y$;
  });
  div = curry$(function(x, y) {
    return Math.floor(x / y);
  });
  mod = curry$(function(x$, y$) {
    var ref$;
    return (((x$) % (ref$ = y$) + ref$) % ref$);
  });
  recip = (function(it) {
    return 1 / it;
  });
  pi = Math.PI;
  tau = pi * 2;
  exp = Math.exp;
  sqrt = Math.sqrt;
  ln = Math.log;
  pow = curry$(function(x$, y$) {
    return Math.pow(x$, y$);
  });
  sin = Math.sin;
  tan = Math.tan;
  cos = Math.cos;
  asin = Math.asin;
  acos = Math.acos;
  atan = Math.atan;
  atan2 = curry$(function(x, y) {
    return Math.atan2(x, y);
  });
  truncate = function(x) {
    return ~~x;
  };
  round = Math.round;
  ceiling = Math.ceil;
  floor = Math.floor;
  isItNaN = function(x) {
    return x !== x;
  };
  even = function(x) {
    return x % 2 === 0;
  };
  odd = function(x) {
    return x % 2 !== 0;
  };
  gcd = curry$(function(x, y) {
    var z;
    x = Math.abs(x);
    y = Math.abs(y);
    while (y !== 0) {
      z = x % y;
      x = y;
      y = z;
    }
    return x;
  });
  lcm = curry$(function(x, y) {
    return Math.abs(Math.floor(x / gcd(x, y) * y));
  });
  module.exports = {
    max: max,
    min: min,
    negate: negate,
    abs: abs,
    signum: signum,
    quot: quot,
    rem: rem,
    div: div,
    mod: mod,
    recip: recip,
    pi: pi,
    tau: tau,
    exp: exp,
    sqrt: sqrt,
    ln: ln,
    pow: pow,
    sin: sin,
    tan: tan,
    cos: cos,
    acos: acos,
    asin: asin,
    atan: atan,
    atan2: atan2,
    truncate: truncate,
    round: round,
    ceiling: ceiling,
    floor: floor,
    isItNaN: isItNaN,
    even: even,
    odd: odd,
    gcd: gcd,
    lcm: lcm
  };
  function curry$(f, bound) {
    var context,
        _curry = function(args) {
          return f.length > 1 ? function() {
            var params = args ? args.concat() : [];
            context = bound ? context || this : this;
            return params.push.apply(params, arguments) < f.length && arguments.length ? _curry.call(context, params) : f.apply(context, params);
          } : f;
        };
    return _curry();
  }
  return module.exports;
});

$__System.registerDynamic("8", ["38", "39", "3a", "3b", "3c"], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  var Func,
      List,
      Obj,
      Str,
      Num,
      id,
      isType,
      replicate,
      prelude,
      toString$ = {}.toString;
  Func = $__require('38');
  List = $__require('39');
  Obj = $__require('3a');
  Str = $__require('3b');
  Num = $__require('3c');
  id = function(x) {
    return x;
  };
  isType = curry$(function(type, x) {
    return toString$.call(x).slice(8, -1) === type;
  });
  replicate = curry$(function(n, x) {
    var i$,
        results$ = [];
    for (i$ = 0; i$ < n; ++i$) {
      results$.push(x);
    }
    return results$;
  });
  Str.empty = List.empty;
  Str.slice = List.slice;
  Str.take = List.take;
  Str.drop = List.drop;
  Str.splitAt = List.splitAt;
  Str.takeWhile = List.takeWhile;
  Str.dropWhile = List.dropWhile;
  Str.span = List.span;
  Str.breakStr = List.breakList;
  prelude = {
    Func: Func,
    List: List,
    Obj: Obj,
    Str: Str,
    Num: Num,
    id: id,
    isType: isType,
    replicate: replicate
  };
  prelude.each = List.each;
  prelude.map = List.map;
  prelude.filter = List.filter;
  prelude.compact = List.compact;
  prelude.reject = List.reject;
  prelude.partition = List.partition;
  prelude.find = List.find;
  prelude.head = List.head;
  prelude.first = List.first;
  prelude.tail = List.tail;
  prelude.last = List.last;
  prelude.initial = List.initial;
  prelude.empty = List.empty;
  prelude.reverse = List.reverse;
  prelude.difference = List.difference;
  prelude.intersection = List.intersection;
  prelude.union = List.union;
  prelude.countBy = List.countBy;
  prelude.groupBy = List.groupBy;
  prelude.fold = List.fold;
  prelude.foldl = List.foldl;
  prelude.fold1 = List.fold1;
  prelude.foldl1 = List.foldl1;
  prelude.foldr = List.foldr;
  prelude.foldr1 = List.foldr1;
  prelude.unfoldr = List.unfoldr;
  prelude.andList = List.andList;
  prelude.orList = List.orList;
  prelude.any = List.any;
  prelude.all = List.all;
  prelude.unique = List.unique;
  prelude.uniqueBy = List.uniqueBy;
  prelude.sort = List.sort;
  prelude.sortWith = List.sortWith;
  prelude.sortBy = List.sortBy;
  prelude.sum = List.sum;
  prelude.product = List.product;
  prelude.mean = List.mean;
  prelude.average = List.average;
  prelude.concat = List.concat;
  prelude.concatMap = List.concatMap;
  prelude.flatten = List.flatten;
  prelude.maximum = List.maximum;
  prelude.minimum = List.minimum;
  prelude.maximumBy = List.maximumBy;
  prelude.minimumBy = List.minimumBy;
  prelude.scan = List.scan;
  prelude.scanl = List.scanl;
  prelude.scan1 = List.scan1;
  prelude.scanl1 = List.scanl1;
  prelude.scanr = List.scanr;
  prelude.scanr1 = List.scanr1;
  prelude.slice = List.slice;
  prelude.take = List.take;
  prelude.drop = List.drop;
  prelude.splitAt = List.splitAt;
  prelude.takeWhile = List.takeWhile;
  prelude.dropWhile = List.dropWhile;
  prelude.span = List.span;
  prelude.breakList = List.breakList;
  prelude.zip = List.zip;
  prelude.zipWith = List.zipWith;
  prelude.zipAll = List.zipAll;
  prelude.zipAllWith = List.zipAllWith;
  prelude.at = List.at;
  prelude.elemIndex = List.elemIndex;
  prelude.elemIndices = List.elemIndices;
  prelude.findIndex = List.findIndex;
  prelude.findIndices = List.findIndices;
  prelude.apply = Func.apply;
  prelude.curry = Func.curry;
  prelude.flip = Func.flip;
  prelude.fix = Func.fix;
  prelude.over = Func.over;
  prelude.split = Str.split;
  prelude.join = Str.join;
  prelude.lines = Str.lines;
  prelude.unlines = Str.unlines;
  prelude.words = Str.words;
  prelude.unwords = Str.unwords;
  prelude.chars = Str.chars;
  prelude.unchars = Str.unchars;
  prelude.repeat = Str.repeat;
  prelude.capitalize = Str.capitalize;
  prelude.camelize = Str.camelize;
  prelude.dasherize = Str.dasherize;
  prelude.values = Obj.values;
  prelude.keys = Obj.keys;
  prelude.pairsToObj = Obj.pairsToObj;
  prelude.objToPairs = Obj.objToPairs;
  prelude.listsToObj = Obj.listsToObj;
  prelude.objToLists = Obj.objToLists;
  prelude.max = Num.max;
  prelude.min = Num.min;
  prelude.negate = Num.negate;
  prelude.abs = Num.abs;
  prelude.signum = Num.signum;
  prelude.quot = Num.quot;
  prelude.rem = Num.rem;
  prelude.div = Num.div;
  prelude.mod = Num.mod;
  prelude.recip = Num.recip;
  prelude.pi = Num.pi;
  prelude.tau = Num.tau;
  prelude.exp = Num.exp;
  prelude.sqrt = Num.sqrt;
  prelude.ln = Num.ln;
  prelude.pow = Num.pow;
  prelude.sin = Num.sin;
  prelude.tan = Num.tan;
  prelude.cos = Num.cos;
  prelude.acos = Num.acos;
  prelude.asin = Num.asin;
  prelude.atan = Num.atan;
  prelude.atan2 = Num.atan2;
  prelude.truncate = Num.truncate;
  prelude.round = Num.round;
  prelude.ceiling = Num.ceiling;
  prelude.floor = Num.floor;
  prelude.isItNaN = Num.isItNaN;
  prelude.even = Num.even;
  prelude.odd = Num.odd;
  prelude.gcd = Num.gcd;
  prelude.lcm = Num.lcm;
  prelude.VERSION = '1.1.2';
  module.exports = prelude;
  function curry$(f, bound) {
    var context,
        _curry = function(args) {
          return f.length > 1 ? function() {
            var params = args ? args.concat() : [];
            context = bound ? context || this : this;
            return params.push.apply(params, arguments) < f.length && arguments.length ? _curry.call(context, params) : f.apply(context, params);
          } : f;
        };
    return _curry();
  }
  return module.exports;
});

$__System.registerDynamic("3d", ["8", "19"], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  var ref$,
      sum,
      map,
      sortBy,
      maximumBy,
      $,
      tanh,
      Vehicle,
      IdmVehicle,
      Delayer,
      LoopMicrosim,
      LoopPlotter,
      out$ = typeof exports != 'undefined' && exports || this;
  ref$ = $__require('8'), sum = ref$.sum, map = ref$.map, sortBy = ref$.sortBy, maximumBy = ref$.maximumBy;
  $ = $__require('19');
  tanh = function(x) {
    var r;
    r = Math.tanh(x);
    if (r !== r) {
      return Math.sign(x);
    }
    return r;
  };
  out$.Vehicle = Vehicle = (function() {
    Vehicle.displayName = 'Vehicle';
    var prototype = Vehicle.prototype,
        constructor = Vehicle;
    function Vehicle() {
      this.position = 0;
      this.velocity = 0;
      this.acceleration = 0;
      this.leader = undefined;
    }
    Vehicle.prototype.step = function() {};
    return Vehicle;
  }());
  out$.IdmVehicle = IdmVehicle = (function(superclass) {
    var prototype = extend$((import$(IdmVehicle, superclass).displayName = 'IdmVehicle', IdmVehicle), superclass).prototype,
        constructor = IdmVehicle;
    function IdmVehicle(arg$) {
      var ref$,
          ref1$;
      ref$ = arg$ != null ? arg$ : {}, this.targetV = (ref1$ = ref$.targetV) != null ? ref1$ : 120 / 3.6, this.timeHeadway = (ref1$ = ref$.timeHeadway) != null ? ref1$ : 1.6, this.minimumGap = (ref1$ = ref$.minimumGap) != null ? ref1$ : 2.0, this.a = (ref1$ = ref$.a) != null ? ref1$ : 1.5, this.b = (ref1$ = ref$.b) != null ? ref1$ : 3.0, this.accelExp = (ref1$ = ref$.accelExp) != null ? ref1$ : 4.0;
    }
    IdmVehicle.prototype.step = function(arg$) {
      var dt,
          dx,
          dv,
          v,
          freeAccel,
          desiredGap;
      dt = arg$.dt, dx = arg$.dx, dv = arg$.dv, v = arg$.v;
      freeAccel = Math.pow(v / this.targetV, this.accelExp);
      if (freeAccel > 1) {
        freeAccel = 1;
      }
      desiredGap = this.minimumGap + this.timeHeadway * v + v * dv / (2 * Math.sqrt(this.a * this.b));
      this.acceleration = this.a * (1 - freeAccel - Math.pow(desiredGap / dx, 2));
      this.velocity += this.acceleration * dt;
      return this.position += this.velocity * dt;
    };
    return IdmVehicle;
  }(Vehicle));
  out$.Delayer = Delayer = (function() {
    Delayer.displayName = 'Delayer';
    var prototype = Delayer.prototype,
        constructor = Delayer;
    function Delayer(model, delay) {
      this.model = model;
      this.delay = delay != null ? delay : 0.3;
      this.t = 0;
      this.buffer = [];
    }
    Delayer.prototype.step = function(state) {
      var dt,
          a,
          old;
      dt = state.dt;
      this.t += dt;
      this.buffer.push({
        t: this.t + this.delay,
        state: state
      });
      a = 0;
      while (this.buffer.length > 0 && this.buffer[0].t <= this.t) {
        old = this.buffer.shift();
        a = this.model.step(old.state);
      }
      return a;
    };
    return Delayer;
  }());
  out$.LoopMicrosim = LoopMicrosim = (function() {
    LoopMicrosim.displayName = 'LoopMicrosim';
    var prototype = LoopMicrosim.prototype,
        constructor = LoopMicrosim;
    function LoopMicrosim(radius) {
      this.radius = radius != null ? radius : 1000;
      this.vehicles = [];
      this.time = 0;
    }
    LoopMicrosim.prototype._updateCircle = function() {
      var i$,
          ref$,
          len$,
          v,
          fullRounds,
          sorted,
          i,
          d,
          this$ = this,
          results$ = [];
      for (i$ = 0, len$ = (ref$ = this.vehicles).length; i$ < len$; ++i$) {
        v = ref$[i$];
        fullRounds = Math.floor(v.position / this.radius);
        v.circlePosition = v.position - this.radius * fullRounds;
      }
      sorted = sortBy(function(it) {
        return it.circlePosition;
      }, this.vehicles);
      for (i$ = 0, len$ = (ref$ = (fn$())).length; i$ < len$; ++i$) {
        i = ref$[i$];
        v = sorted[i];
        v.leader = sorted[(i + 1) % sorted.length];
        d = v.leader.circlePosition - v.circlePosition;
        if (d <= 0) {
          d += this.radius;
        }
        v.headway = d;
        results$.push(v.velocityDiff = v.velocity - v.leader.velocity);
      }
      return results$;
      function fn$() {
        var i$,
            to$,
            results$ = [];
        for (i$ = 0, to$ = sorted.length; i$ < to$; ++i$) {
          results$.push(i$);
        }
        return results$;
      }
    };
    LoopMicrosim.prototype.step = function(dt) {
      var i$,
          ref$,
          len$,
          v;
      this._updateCircle();
      for (i$ = 0, len$ = (ref$ = this.vehicles).length; i$ < len$; ++i$) {
        v = ref$[i$];
        v.step({
          dt: dt,
          dx: v.headway,
          v: v.velocity,
          dv: v.velocityDiff
        });
      }
      return this.time += dt;
    };
    LoopMicrosim.prototype.position2d = function(position) {
      var angle;
      angle = position / this.radius * Math.PI * 2;
      return [Math.sin(angle) * this.radius, Math.cos(angle) * this.radius];
    };
    LoopMicrosim.prototype.bestNewPosition = function() {
      var follower,
          this$ = this;
      this._updateCircle();
      follower = maximumBy(function(it) {
        return it.headway;
      }, this.vehicles);
      if (follower == null) {
        return 0;
      }
      return follower.position + follower.headway / 2.0;
    };
    LoopMicrosim.prototype.addVehicle = function(v) {
      v.position == null && (v.position = this.bestNewPosition());
      v.velocity == null && (v.velocity = 0);
      v.acceleration == null && (v.acceleration = 0);
      this.vehicles.push(v);
      return this._updateCircle();
    };
    LoopMicrosim.prototype.isInStandstill = function() {
      var maxvel,
          maxaccel,
          this$ = this;
      if (this.time === 0) {
        return false;
      }
      maxvel = Math.max.apply(Math, map(Math.abs, map(function(it) {
        return it.velocity;
      }, this.vehicles)));
      maxaccel = Math.max.apply(Math, map(Math.abs, map(function(it) {
        return it.acceleration;
      }, this.vehicles)));
      return maxaccel < 1 && maxvel < 1;
    };
    return LoopMicrosim;
  }());
  out$.LoopPlotter = LoopPlotter = (function() {
    LoopPlotter.displayName = 'LoopPlotter';
    var prototype = LoopPlotter.prototype,
        constructor = LoopPlotter;
    function LoopPlotter(container, env) {
      this.container = container;
      this.env = env;
    }
    LoopPlotter.prototype.render = function() {
      var d,
          relpos,
          vs,
          meanVelocity,
          i$,
          len$,
          i,
          v,
          pos,
          e,
          this$ = this,
          results$ = [];
      this.container.empty();
      d = this.env.radius * 2;
      relpos = function(pos) {
        return (pos + d / 2.0) / d * 100;
      };
      vs = this.env.vehicles;
      meanVelocity = sum(map(function(it) {
        return it.velocity * 3.6 / vs.length;
      }, vs));
      for (i$ = 0, len$ = vs.length; i$ < len$; ++i$) {
        i = i$;
        v = vs[i$];
        pos = this.env.position2d(v.position);
        e = $("<div>").css({
          "background-color": "black",
          position: "absolute",
          left: relpos(pos[0]) + "%",
          top: relpos(pos[1]) + "%",
          width: "10px",
          height: "10px"
        });
        if (v.higlight) {
          $('#velocity').text(v.velocity * 3.6);
          $('#acceleration').text(v.acceleration);
          $('#time').text(this.env.time);
          $('#meanvelocity').text(meanVelocity);
          e.css({"background-color": "red"});
        }
        results$.push(this.container.append(e));
      }
      return results$;
    };
    return LoopPlotter;
  }());
  function extend$(sub, sup) {
    function fun() {}
    fun.prototype = (sub.superclass = sup).prototype;
    (sub.prototype = new fun).constructor = sub;
    if (typeof sup.extended == 'function')
      sup.extended(sub);
    return sub;
  }
  function import$(obj, src) {
    var own = {}.hasOwnProperty;
    for (var key in src)
      if (own.call(src, key))
        obj[key] = src[key];
    return obj;
  }
  return module.exports;
});

$__System.registerDynamic("3e", [], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  (function(exports) {
    'use strict';
    function shuffle(array) {
      var currentIndex = array.length,
          temporaryValue,
          randomIndex;
      ;
      while (0 !== currentIndex) {
        randomIndex = Math.floor(Math.random() * currentIndex);
        currentIndex -= 1;
        temporaryValue = array[currentIndex];
        array[currentIndex] = array[randomIndex];
        array[randomIndex] = temporaryValue;
      }
      return array;
    }
    exports.knuthShuffle = shuffle;
  }('undefined' !== typeof exports && exports || 'undefined' !== typeof window && window || global));
  return module.exports;
});

$__System.registerDynamic("23", ["20", "19", "1a", "28", "2c", "22", "2e", "31", "8", "24", "37", "3d", "3e"], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  var P,
      Co,
      $,
      seqr,
      ref$,
      addGround,
      Scene,
      addVehicle,
      NonSteeringControl,
      DefaultEngineSound,
      BellPlayer,
      NoisePlayer,
      assets,
      prelude,
      ui,
      exportScenario,
      DummyScene,
      baseScene,
      minimalScenario,
      basePedalScene,
      catchthething,
      addReactionTest,
      addBlinder,
      addBlinderTask,
      addForcedBlinderTask,
      collisionReason,
      failOnCollision,
      speedControl,
      IdmVehicle,
      LoopMicrosim,
      MicrosimWrapper,
      shuffleArray,
      TargetSpeedController,
      followInTraffic,
      pursuitDiscriminationBase,
      out$ = typeof exports != 'undefined' && exports || this;
  P = $__require('20');
  Co = P.coroutine;
  $ = $__require('19');
  seqr = $__require('1a');
  ref$ = $__require('28'), addGround = ref$.addGround, Scene = ref$.Scene;
  addVehicle = $__require('2c').addVehicle;
  NonSteeringControl = $__require('22').NonSteeringControl;
  ref$ = $__require('2e'), DefaultEngineSound = ref$.DefaultEngineSound, BellPlayer = ref$.BellPlayer, NoisePlayer = ref$.NoisePlayer;
  assets = $__require('31');
  prelude = $__require('8');
  ui = $__require('24');
  exportScenario = function(name, impl) {
    var scn;
    scn = seqr.bind(impl);
    scn.scenarioName = name;
    module.exports[name] = scn;
    return scn;
  };
  DummyScene = function() {
    return {
      beforePhysics: Signal(),
      afterPhysics: Signal(),
      beforeRender: Signal(),
      onRender: Signal(),
      onStart: Signal(),
      onExit: Signal(),
      onTickHandled: Signal(),
      camera: {
        updateProjectionMatrix: function() {},
        add: function() {}
      },
      visual: {
        add: function() {},
        traverse: function() {},
        addEventListener: function() {}
      },
      physics: {
        add: function() {},
        addEventListener: function() {},
        removeBody: function() {}
      },
      preroll: function() {},
      tick: function() {},
      bindPhys: function() {}
    };
  };
  out$.baseScene = baseScene = seqr.bind(function*(env) {
    var controls,
        audioContext,
        L,
        scene,
        sky,
        player,
        engineSounds,
        gainNode;
    controls = env.controls, audioContext = env.audioContext, L = env.L;
    scene = new Scene;
    (yield P.resolve(addGround(scene)));
    sky = (yield P.resolve(assets.addSky(scene)));
    scene.playerControls = controls;
    player = (yield addVehicle(scene, controls, {objectName: 'player'}));
    player.eye.add(scene.camera);
    player.physical.position.x = -1.75;
    scene.player = player;
    scene.player.speedometer = ui.gauge(env, {
      name: L("Speed"),
      unit: L("km/h"),
      value: function() {
        var speed;
        speed = scene.player.getSpeed() * 3.6;
        return Math.round(speed);
      }
    });
    engineSounds = (yield DefaultEngineSound(audioContext));
    gainNode = audioContext.createGain();
    gainNode.connect(audioContext.destination);
    engineSounds.connect(gainNode);
    scene.afterPhysics.add(function() {
      var rev,
          gain;
      rev = Math.abs(player.getSpeed()) / (200 / 3.6);
      rev = Math.max(0.1, rev);
      rev = (rev + 0.1) / 1.1;
      gain = scene.playerControls.throttle;
      gain = (gain + 0.5) / 1.5;
      gainNode.gain.value = gain;
      return engineSounds.setPitch(rev * 2000);
    });
    scene.onStart.add(engineSounds.start);
    scene.onExit.add(engineSounds.stop);
    scene.preroll = function() {
      var n,
          t,
          i$,
          x$,
          ref$,
          len$;
      scene.tick(1 / 60);
      n = 100;
      t = Date.now();
      for (i$ = 0, len$ = (ref$ = (fn$())).length; i$ < len$; ++i$) {
        x$ = ref$[i$];
        scene.tick(1 / 60);
      }
      return console.log("Prewarming FPS", n / (Date.now() - t) * 1000);
      function fn$() {
        var i$,
            to$,
            results$ = [];
        for (i$ = 0, to$ = n; i$ <= to$; ++i$) {
          results$.push(i$);
        }
        return results$;
      }
    };
    return scene;
  });
  out$.minimalScenario = minimalScenario = seqr.bind(function*(env) {
    var scene;
    scene = new Scene;
    addGround(scene);
    scene.preroll = function() {};
    this['let']('scene', scene);
    return (yield this.get('done'));
  });
  exportScenario('freeDriving', function*(env) {
    var scene;
    scene = (yield baseScene(env));
    this['let']('scene', scene);
    return (yield this.get('done'));
  });
  out$.basePedalScene = basePedalScene = function(env) {
    var ref$;
    env = (ref$ = clone$(env), ref$.controls = NonSteeringControl(env.controls), ref$);
    return baseScene(env);
  };
  catchthething = $__require('37');
  addReactionTest = seqr.bind(function*(scene, env) {
    var react,
        screen;
    react = (yield catchthething.React());
    screen = (yield assets.SceneDisplay());
    screen.object.position.z = -0.3;
    screen.object.scale.set(0.12, 0.12, 0.12);
    screen.object.visible = false;
    scene.camera.add(screen.object);
    env.controls.change(function(btn, isOn) {
      if (btn === "catch" && isOn && screen.object.visible) {
        react['catch']();
      } else if (btn === "blinder") {
        screen.object.visible = isOn;
      }
    });
    react.event(function(type) {
      return env.logger.write({reactionGameEvent: type});
    });
    scene.onRender.add(function(dt) {
      react.tick(dt);
      return env.renderer.render(react.scene, react.camera, screen.renderTarget, true);
    });
    return react;
  });
  addBlinder = function(scene, env) {
    var mask,
        self,
        showMask;
    mask = new THREE.Mesh(new THREE.PlaneGeometry(0.1 * 16 / 9, 0.1), new THREE.MeshBasicMaterial({color: 0x000000}));
    mask.position.z = -0.3;
    mask.position.x = 0.03;
    mask.position.y = -0.03;
    scene.camera.add(mask);
    self = {
      change: Signal(),
      glances: 0
    };
    self._showMask = showMask = function() {
      if (mask.visible) {
        return;
      }
      mask.visible = true;
      self.change.dispatch(true);
      return env.logger.write({blinder: true});
    };
    self._showMask();
    self._liftMask = function() {
      mask.visible = false;
      self.glances += 1;
      self.change.dispatch(false);
      env.logger.write({blinder: false});
      return setTimeout(showMask, 300);
    };
    return self;
  };
  addBlinderTask = function(scene, env) {
    var self;
    self = addBlinder(scene, env);
    ui.gauge(env, {
      name: env.L("Glances"),
      unit: "",
      value: function() {
        return self.glances;
      }
    });
    env.controls.change(function(btn, isOn) {
      if (btn !== 'blinder') {
        return;
      }
      if (isOn !== true) {
        return;
      }
      return self._liftMask();
    });
    return self;
  };
  addForcedBlinderTask = function(scene, env, arg$) {
    var interval,
        ref$,
        self,
        id;
    interval = (ref$ = (arg$ != null ? arg$ : {}).interval) != null ? ref$ : 2;
    self = addBlinder(scene, env);
    id = setInterval(bind$(self, '_liftMask'), interval * 1000);
    env['finally'](function() {
      return clearInterval(id);
    });
    return self;
  };
  exportScenario('runTheLight', function*(env) {
    var scene,
        startLight,
        this$ = this;
    this['let']('intro', {
      title: env.L("Run the light"),
      subtitle: env.L("(Just this once)"),
      content: $(env.L("%runTheLight.intro"))
    });
    scene = (yield basePedalScene(env));
    startLight = (yield assets.TrafficLight());
    startLight.position.x = -4;
    startLight.position.z = 6;
    startLight.addTo(scene);
    this['let']('scene', scene);
    (yield this.get('run'));
    scene.player.onCollision(function(e) {
      return this$['let']('done', {
        passed: true,
        outro: {
          title: env.L("Passed"),
          content: env.L('%runTheLight.outro')
        }
      });
    });
    return (yield this.get('done'));
  });
  collisionReason = function(arg$, e) {
    var L;
    L = arg$.L;
    switch (e.body.objectClass) {
      case 'traffic-light':
        return L("You ran the red light!");
      case 'stop-sign':
        return L("You ran the stop sign!");
      default:
        return L("You crashed!");
    }
  };
  failOnCollision = function(env, scn, scene) {
    return scene.player.onCollision(function(e) {
      var reason;
      reason = collisionReason(env, e);
      scn['let']('done', {
        passed: false,
        outro: {
          title: env.L("Oops!"),
          content: reason
        }
      });
      return false;
    });
  };
  exportScenario('closeTheGap', function*(env) {
    var scene,
        leader,
        distanceToLeader,
        this$ = this;
    this['let']('intro', {
      title: env.L("Close the gap"),
      content: env.L('%closeTheGap.intro')
    });
    scene = (yield basePedalScene(env));
    leader = (yield addVehicle(scene));
    leader.physical.position.x = scene.player.physical.position.x;
    leader.physical.position.z = 100;
    failOnCollision(env, this, scene);
    this['let']('scene', scene);
    (yield this.get('run'));
    distanceToLeader = function() {
      var rawDist;
      rawDist = scene.player.physical.position.distanceTo(leader.physical.position);
      return rawDist - scene.player.physical.boundingRadius - leader.physical.boundingRadius;
    };
    env.controls.change(function(btn, isOn) {
      var distance;
      if (!(btn === 'catch' && isOn)) {
        return;
      }
      distance = distanceToLeader();
      distance += 1.47;
      this$['let']('done', {
        passed: true,
        outro: {
          title: env.L("Passed"),
          content: env.L("%closeTheGap.outro", {distance: distance})
        }
      });
      return false;
    });
    return (yield this.get('done'));
  });
  exportScenario('throttleAndBrake', function*(env) {
    var L,
        scene,
        goalDistance,
        startLight,
        x$,
        stopSign,
        finishSign,
        startTime,
        this$ = this;
    L = env.L;
    this['let']('intro', {
      title: L("Throttle and brake"),
      content: L('%throttleAndBrake.intro')
    });
    scene = (yield basePedalScene(env));
    goalDistance = 200;
    startLight = (yield assets.TrafficLight());
    startLight.position.x = -4;
    startLight.position.z = 6;
    startLight.addTo(scene);
    x$ = stopSign = (yield assets.StopSign());
    x$.position.x = -4;
    x$.position.z = goalDistance + 10;
    x$.addTo(scene);
    failOnCollision(env, this, scene);
    finishSign = (yield assets.FinishSign());
    finishSign.position.z = goalDistance;
    finishSign.addTo(scene);
    ui.gauge(env, {
      name: L("Time"),
      unit: L("s"),
      value: function() {
        if (typeof startTime == 'undefined' || startTime === null) {
          return 0 .toFixed(2);
        }
        return (scene.time - startTime).toFixed(2);
      }
    });
    this['let']('scene', scene);
    (yield this.get('run'));
    (yield P.delay(2000));
    (yield startLight.switchToGreen());
    startTime = scene.time;
    finishSign.bodyPassed(scene.player.physical).then(function() {
      return scene.onTickHandled(function() {
        var time;
        if (Math.abs(scene.player.getSpeed()) > 0.1) {
          return;
        }
        time = scene.time - startTime;
        this$['let']('done', {
          passed: true,
          outro: {
            title: L("Passed"),
            content: L('%throttleAndBrake.outro', {time: time})
          }
        });
        return false;
      });
    });
    return (yield this.get('done'));
  });
  speedControl = exportScenario('speedControl', function*(env) {
    var L,
        scene,
        limits,
        goalDistance,
        i$,
        len$,
        ref$,
        dist,
        limit,
        sign,
        currentLimit,
        limitSign,
        illGainsMultiplier,
        illGains,
        timePenalty,
        startLight,
        x$,
        stopSign,
        finishSign,
        startTime,
        this$ = this;
    L = env.L;
    this['let']('intro', {
      title: L("Speed control"),
      content: L("%speedControl.intro")
    });
    scene = (yield basePedalScene(env));
    limits = [[-Infinity, 50], [20, 50], [200, 30], [250, 80], [500, 60]];
    goalDistance = 700;
    for (i$ = 0, len$ = limits.length; i$ < len$; ++i$) {
      ref$ = limits[i$], dist = ref$[0], limit = ref$[1];
      sign = (yield assets.SpeedSign(limit));
      sign.position.z = dist;
      sign.position.x = -4;
      scene.visual.add(sign);
    }
    limits.reverse();
    currentLimit = function() {
      var mypos,
          i$,
          ref$,
          len$,
          ref1$,
          distance,
          limit;
      mypos = scene.player.physical.position.z;
      for (i$ = 0, len$ = (ref$ = limits).length; i$ < len$; ++i$) {
        ref1$ = ref$[i$], distance = ref1$[0], limit = ref1$[1];
        if (distance < mypos) {
          break;
        }
      }
      return limit;
    };
    limitSign = ui.gauge(env, {
      name: L("Speed limit"),
      unit: L("km/h"),
      value: currentLimit
    });
    illGainsMultiplier = 10;
    illGains = 0;
    timePenalty = 0;
    scene.afterPhysics(function(dt) {
      var limit,
          speed,
          traveled,
          legalMinTime,
          timeGained;
      if (typeof startTime == 'undefined' || startTime === null) {
        return;
      }
      limit = currentLimit();
      speed = Math.abs(scene.player.getSpeed() * 3.6);
      if (speed <= limit) {
        limitSign.normal();
        return;
      }
      limitSign.warning();
      traveled = (speed / 3.6) * dt;
      legalMinTime = traveled / (limit / 3.6);
      timeGained = legalMinTime - dt;
      illGains += timeGained;
      return timePenalty = illGains * illGainsMultiplier;
    });
    ui.gauge(env, {
      name: L("Penalty"),
      unit: "s",
      value: function() {
        return timePenalty.toFixed(2);
      }
    });
    startLight = (yield assets.TrafficLight());
    startLight.position.x = -4;
    startLight.position.z = 6;
    startLight.addTo(scene);
    x$ = stopSign = (yield assets.StopSign());
    x$.position.x = -4;
    x$.position.z = goalDistance + 10;
    x$.addTo(scene);
    failOnCollision(env, this, scene);
    scene.player.onCollision(function(e) {
      this$['let']('done', {
        passed: false,
        outro: {
          title: L("Oops!"),
          content: L("You ran the red light!")
        }
      });
      return false;
    });
    finishSign = (yield assets.FinishSign());
    finishSign.position.z = goalDistance;
    finishSign.addTo(scene);
    this['let']('scene', scene);
    (yield this.get('run'));
    (yield P.delay(1000));
    (yield startLight.switchToGreen());
    startTime = scene.time;
    finishSign.bodyPassed(scene.player.physical).then(function() {
      return scene.onTickHandled(function() {
        var time;
        if (Math.abs(scene.player.getSpeed()) > 0.1) {
          return;
        }
        time = scene.time - startTime;
        this$['let']('done', {
          passed: true,
          outro: {
            title: L("Passed"),
            content: L('%speedControl.outro', {
              time: time,
              timePenalty: timePenalty
            })
          }
        });
        return false;
      });
    });
    return (yield this.get('done'));
  });
  exportScenario('blindSpeedControl', function*(env) {
    var L,
        base,
        intro,
        scene,
        result;
    L = env.L;
    base = speedControl(env);
    intro = (yield base.get('intro'));
    this['let']('intro', {
      title: L("Anticipatory speed control"),
      content: L('%blindSpeedControl.intro')
    });
    scene = (yield base.get('scene'));
    addBlinderTask(scene, env);
    this['let']('scene', scene);
    (yield this.get('run'));
    base['let']('run');
    result = (yield base.get('done'));
    this['let']('done', result);
    return result;
  });
  ref$ = $__require('3d'), IdmVehicle = ref$.IdmVehicle, LoopMicrosim = ref$.LoopMicrosim;
  MicrosimWrapper = (function() {
    MicrosimWrapper.displayName = 'MicrosimWrapper';
    var prototype = MicrosimWrapper.prototype,
        constructor = MicrosimWrapper;
    function MicrosimWrapper(phys) {
      this.phys = phys;
    }
    Object.defineProperty(MicrosimWrapper.prototype, 'position', {
      get: function() {
        return this.phys.position.z;
      },
      configurable: true,
      enumerable: true
    });
    Object.defineProperty(MicrosimWrapper.prototype, 'velocity', {
      get: function() {
        return this.phys.velocity.z;
      },
      configurable: true,
      enumerable: true
    });
    Object.defineProperty(MicrosimWrapper.prototype, 'acceleration', {
      get: function() {
        return null;
      },
      configurable: true,
      enumerable: true
    });
    MicrosimWrapper.prototype.step = function() {};
    return MicrosimWrapper;
  }());
  shuffleArray = $__require('3e').knuthShuffle;
  TargetSpeedController = $__require('22').TargetSpeedController;
  followInTraffic = exportScenario('followInTraffic', function*(env, arg$) {
    var distance,
        ref$,
        L,
        scene,
        startLight,
        goalDistance,
        finishSign,
        maximumFuelFlow,
        constantConsumption,
        draftingCoeff,
        consumption,
        leaderControls,
        leader,
        speeds,
        speedDuration,
        sequence,
        res$,
        i$,
        len$,
        i,
        speed,
        headway,
        cumHeadway,
        averageHeadway,
        distanceToLeader,
        startTime,
        this$ = this;
    distance = (ref$ = (arg$ != null ? arg$ : {}).distance) != null ? ref$ : 2000;
    L = env.L;
    this['let']('intro', {
      title: L("Supermiler"),
      content: $(L("%followInTraffic.intro"))
    });
    scene = (yield basePedalScene(env));
    startLight = (yield assets.TrafficLight());
    startLight.position.x = -4;
    startLight.position.z = 6;
    startLight.addTo(scene);
    goalDistance = distance;
    finishSign = (yield assets.FinishSign());
    finishSign.position.z = goalDistance;
    finishSign.addTo(scene);
    finishSign.visual.visible = false;
    scene.player.onCollision(function(e) {
      var reason;
      reason = L("You crashed!");
      if (e.body.objectClass === "traffic-light") {
        reason = L("You ran the red light!");
      }
      this$['let']('done', {
        passed: false,
        outro: {
          title: L("Oops!"),
          content: reason
        }
      });
      return false;
    });
    maximumFuelFlow = 200 / 60 / 1000;
    constantConsumption = maximumFuelFlow * 0.1;
    draftingCoeff = function(d) {
      return Math.exp(0) - Math.exp(-(d + 5.6) * 0.1);
    };
    consumption = {
      time: 0,
      distance: 0,
      instant: 0,
      total: 0,
      noDraftTotal: 0,
      avgLitersPer100km: function(consumption) {
        var metersPerLiter;
        consumption == null && (consumption = this.total);
        metersPerLiter = this.distance / consumption;
        return 1.0 / metersPerLiter * 1000 * 100;
      },
      instLitersPer100km: function() {
        var metersPerLiter;
        metersPerLiter = Math.abs(scene.player.getSpeed()) / this.instant;
        return 1.0 / metersPerLiter * 1000 * 100;
      }
    };
    scene.afterPhysics.add(function(dt) {
      var instant;
      if (typeof startTime == 'undefined' || startTime === null) {
        return;
      }
      consumption.time += dt;
      consumption.distance += dt * Math.abs(scene.player.getSpeed());
      instant = env.controls.throttle * maximumFuelFlow + constantConsumption;
      consumption.instant = instant * draftingCoeff(distanceToLeader());
      consumption.total += consumption.instant * dt;
      consumption.noDraftTotal += instant * dt;
    });
    ui.gauge(env, {
      name: L("Current consumption"),
      unit: "l/100km",
      range: [0, 30],
      format: function(v) {
        if (Math.abs(scene.player.getSpeed()) < 1.0) {
          return null;
        }
        return v.toFixed(2);
      },
      value: function() {
        var c;
        c = consumption.instLitersPer100km();
        return c;
      }
    });
    ui.gauge(env, {
      name: L("Average consumption"),
      unit: "l/100km",
      range: [0, 30],
      format: function(v) {
        if (consumption.distance < 1) {
          return null;
        }
        return v.toFixed(2);
      },
      value: function() {
        return consumption.avgLitersPer100km();
      }
    });
    leaderControls = new TargetSpeedController;
    leader = (yield addVehicle(scene, leaderControls));
    leader.physical.position.x = -1.75;
    leader.physical.position.z = 10;
    speeds = [0, 30, 40, 50, 60, 70, 80, 0, 30, 40, 50, 60, 70, 80];
    shuffleArray(speeds);
    while (speeds[speeds.length - 1] === 0) {
      shuffleArray(speeds);
    }
    speedDuration = 10;
    res$ = [];
    for (i$ = 0, len$ = speeds.length; i$ < len$; ++i$) {
      i = i$;
      speed = speeds[i$];
      res$.push([(i + 1) * speedDuration, speed / 3.6]);
    }
    sequence = res$;
    scene.afterPhysics.add(function(dt) {
      if (scene.time > sequence[0][0] && sequence.length > 1) {
        sequence = sequence.slice(1);
      }
      leaderControls.target = sequence[0][1];
      return leaderControls.tick(leader.getSpeed(), dt);
    });
    headway = {
      cumulative: 0,
      time: 0,
      average: function() {
        return this.cumulative / this.time;
      }
    };
    cumHeadway = 0;
    averageHeadway = 0;
    scene.afterPhysics(function(dt) {
      if (typeof startTime == 'undefined' || startTime === null) {
        return;
      }
      headway.cumulative += dt * distanceToLeader();
      return headway.time += dt;
    });
    distanceToLeader = function() {
      var rawDist;
      rawDist = scene.player.physical.position.distanceTo(leader.physical.position);
      return rawDist - scene.player.physical.boundingRadius - leader.physical.boundingRadius;
    };
    scene.draftIndicator = ui.gauge(env, {
      name: L("Draft saving"),
      unit: "%",
      value: function() {
        var c;
        c = draftingCoeff(distanceToLeader());
        return ((1 - c) * 100).toFixed(1);
      }
    });
    finishSign.bodyPassed(scene.player.physical).then(function() {
      return this$['let']('done', {
        passed: true,
        outro: {
          title: L("Passed!"),
          content: L('%followInTraffic.outro', {consumption: consumption})
        }
      });
    });
    this['let']('scene', scene);
    (yield this.get('run'));
    (yield P.delay(1000));
    (yield startLight.switchToGreen());
    startTime = scene.time;
    return (yield this.get('done'));
  });
  exportScenario('blindFollowInTraffic', function*(env) {
    var L,
        base,
        intro,
        scene,
        result;
    L = env.L;
    base = followInTraffic(env);
    intro = (yield base.get('intro'));
    this['let']('intro', {
      title: L("Anticipating supermiler"),
      content: L('%blindFollowInTraffic.intro')
    });
    scene = (yield base.get('scene'));
    scene.draftIndicator.el.hide();
    addBlinderTask(scene, env);
    this['let']('scene', scene);
    (yield this.get('run'));
    base['let']('run');
    this.get('done').then(function(result) {
      return base['let']('done', result);
    });
    result = (yield base.get('done'));
    this['let']('done', result);
    return result;
  });
  exportScenario('forcedBlindFollowInTraffic', function*(env, opts) {
    var L,
        base,
        intro,
        scene,
        result;
    L = env.L;
    base = followInTraffic(env, {distance: 1000});
    intro = (yield base.get('intro'));
    this['let']('intro', {
      title: L("Distracted supermiler"),
      content: L('%forcedBlindFollowInTraffic.intro')
    });
    scene = (yield base.get('scene'));
    scene.draftIndicator.el.hide();
    addForcedBlinderTask(scene, env, opts);
    this['let']('scene', scene);
    (yield this.get('run'));
    base['let']('run');
    this.get('done').then(function(result) {
      return base['let']('done', result);
    });
    result = (yield base.get('done'));
    this['let']('done', result);
    return result;
  });
  exportScenario('participantInformation', function*(env) {
    var L,
        currentYear,
        radioSelect,
        dialogs,
        i,
        result,
        results$ = [];
    L = env.L;
    currentYear = (new Date).getFullYear();
    radioSelect = function(name) {
      var options,
          res$,
          i$,
          to$,
          len$,
          ref$,
          value,
          label,
          results$ = [];
      res$ = [];
      for (i$ = 1, to$ = arguments.length; i$ < to$; ++i$) {
        res$.push(arguments[i$]);
      }
      options = res$;
      for (i$ = 0, len$ = options.length; i$ < len$; ++i$) {
        ref$ = options[i$], value = ref$.value, label = ref$.label;
        results$.push($("<div class=\"radio\">\n	<label>\n		<input type=\"radio\" name=\"" + name + "\" value=\"" + value + "\">\n		" + label + "\n	</label>\n</div>"));
      }
      return results$;
    };
    dialogs = [function() {
      this('title').text(L("Welcome to the experiment"));
      this('text').append(L("%intro.introduction"));
      this('accept').text(L("Next"));
      return this('cancel-button').hide();
    }, function() {
      this('title').text(L("Participation is voluntary"));
      this('text').append(L("%intro.participantRights"));
      this('cancel').text(L("Previous"));
      return this('accept').text(L("I wish to participate"));
    }, function() {
      this('title').text(L("Collection and use of data"));
      this('text').append(L("%intro.dataUse"));
      this('cancel').text(L("Previous"));
      return this('accept').text(L("I accept the usage of my data"));
    }, function() {
      this('title').text(L("Background information"));
      this('text').append(L("%intro.backgroundInfo"));
      this('accept').text(L("Next"));
      return this('cancel').text(L("Previous"));
    }, function() {
      var input;
      this('title').text(L("E-mail address"));
      this('text').append(L("%intro.email"));
      this('accept').text(L("Next"));
      this('cancel').text(L("Previous"));
      input = $('<input name="email" type="email" style="color: black">').prop("placeholder", L("E-mail address")).appendTo(this('inputs'));
      return setTimeout(bind$(input, 'focus'), 0);
    }, function() {
      var input;
      this('title').text(L("Birth year"));
      this('accept').text(L("Next"));
      this('cancel').text(L("Previous"));
      input = $("<input name=\"birthyear\" type=\"number\" min=\"1900\" max=\"" + currentYear + "\" style=\"color: black\">").appendTo(this('inputs'));
      return setTimeout(bind$(input, 'focus'), 0);
    }, function() {
      this('title').text(L("Gender"));
      this('accept').text(L("Next"));
      this('cancel').text(L("Previous"));
      return this('inputs').append(radioSelect("gender", {
        value: 'female',
        label: L("Female")
      }, {
        value: 'male',
        label: L("Male")
      }));
    }, function() {
      var input;
      this('title').text(L("Driving license year"));
      this('text').append(L("%intro.license"));
      this('accept').text(L("Next"));
      this('cancel').text(L("Previous"));
      input = $("<input name=\"drivinglicenseyear\" type=\"number\" min=\"1900\" max=\"" + currentYear + "\" style=\"color: black\">").appendTo(this('inputs'));
      return setTimeout(bind$(input, 'focus'), 0);
    }, function() {
      this('title').text(L("Past year driving"));
      this('text').append(L("On average, how frequently have you driven during the <strong>past year</strong>."));
      this('accept').text(L("Next"));
      this('cancel').text(L("Previous"));
      return this('inputs').append(radioSelect("drivingFreqPastYear", {
        value: 'daily',
        label: L("Most days")
      }, {
        value: 'weekly',
        label: L("Most weeks")
      }, {
        value: 'monthly',
        label: L("Most months")
      }, {
        value: 'yearly',
        label: L("Few times a year")
      }, {
        value: 'none',
        label: L("Not at all")
      }));
    }, function() {
      this('title').text(L("Lifetime driving"));
      this('text').append(L("On average, how frequently have you driven <strong>since you got your driver's license</strong>."));
      this('accept').text(L("Next"));
      this('cancel').text(L("Previous"));
      return this('inputs').append(radioSelect("drivingFreqTotal", {
        value: 'daily',
        label: L("Most days")
      }, {
        value: 'weekly',
        label: L("Most weeks")
      }, {
        value: 'monthly',
        label: L("Most months")
      }, {
        value: 'yearly',
        label: L("Few times a year")
      }, {
        value: 'none',
        label: L("Not at all")
      }));
    }];
    i = 0;
    while (i < dialogs.length) {
      result = (yield ui.inputDialog(env, dialogs[i]));
      console.log(result);
      if (result.canceled) {
        i -= 2;
      }
      results$.push(i += 1);
    }
    return results$;
  });
  exportScenario('participantInformationBlindPursuit', function*(env) {
    var L,
        currentYear,
        radioSelect,
        dialogs,
        i,
        result,
        results$ = [];
    L = env.L;
    currentYear = (new Date).getFullYear();
    radioSelect = function(name) {
      var options,
          res$,
          i$,
          to$,
          len$,
          ref$,
          value,
          label,
          results$ = [];
      res$ = [];
      for (i$ = 1, to$ = arguments.length; i$ < to$; ++i$) {
        res$.push(arguments[i$]);
      }
      options = res$;
      for (i$ = 0, len$ = options.length; i$ < len$; ++i$) {
        ref$ = options[i$], value = ref$.value, label = ref$.label;
        results$.push($("<div class=\"radio\">\n	<label>\n		<input type=\"radio\" name=\"" + name + "\" value=\"" + value + "\">\n		" + label + "\n	</label>\n</div>"));
      }
      return results$;
    };
    dialogs = [function() {
      this('title').text(L("Welcome to the experiment"));
      this('text').append(L("%introBlindPursuit.introduction"));
      this('accept').text(L("Next"));
      return this('cancel-button').hide();
    }, function() {
      this('title').text(L("Participation is voluntary"));
      this('text').append(L("%intro.participantRights"));
      this('cancel').text(L("Previous"));
      return this('accept').text(L("I wish to participate"));
    }, function() {
      this('title').text(L("Possible eye strain"));
      this('text').append(L("%introBlindPursuit.eyeStrain"));
      this('cancel').text(L("Previous"));
      return this('accept').text(L("OK"));
    }, function() {
      this('title').text(L("Collection and use of data"));
      this('text').append(L("%intro.dataUse"));
      this('cancel').text(L("Previous"));
      return this('accept').text(L("I accept the usage of my data"));
    }, function() {
      this('title').text(L("Background information"));
      this('text').append(L("%intro.backgroundInfo"));
      this('accept').text(L("Next"));
      return this('cancel').text(L("Previous"));
    }, function() {
      var input;
      this('title').text(L("E-mail address"));
      this('text').append(L("%intro.email"));
      this('accept').text(L("Next"));
      this('cancel').text(L("Previous"));
      input = $('<input name="email" type="email" style="color: black">').prop("placeholder", L("E-mail address")).appendTo(this('inputs'));
      return setTimeout(bind$(input, 'focus'), 0);
    }, function() {
      var input;
      this('title').text(L("Birth year"));
      this('accept').text(L("Next"));
      this('cancel').text(L("Previous"));
      input = $("<input name=\"birthyear\" type=\"number\" min=\"1900\" max=\"" + currentYear + "\" style=\"color: black\">").appendTo(this('inputs'));
      return setTimeout(bind$(input, 'focus'), 0);
    }, function() {
      this('title').text(L("Gender"));
      this('accept').text(L("Next"));
      this('cancel').text(L("Previous"));
      return this('inputs').append(radioSelect("gender", {
        value: 'female',
        label: L("Female")
      }, {
        value: 'male',
        label: L("Male")
      }));
    }];
    i = 0;
    while (i < dialogs.length) {
      result = (yield ui.inputDialog(env, dialogs[i]));
      console.log(result);
      if (result.canceled) {
        i -= 2;
      }
      results$.push(i += 1);
    }
    return results$;
  });
  exportScenario('experimentOutro', function*(env, cb) {
    var L;
    cb == null && (cb = function() {});
    L = env.L;
    return (yield ui.instructionScreen(env, function() {
      var args,
          res$,
          i$,
          to$,
          ref$;
      res$ = [];
      for (i$ = 0, to$ = arguments.length; i$ < to$; ++i$) {
        res$.push(arguments[i$]);
      }
      args = res$;
      this('title').append(L("The experiment is done!"));
      this('content').append(L('%experimentOutro'));
      this('accept-button').hide();
      return cb.apply(this, (ref$ = [env]).concat.apply(ref$, args));
    }));
  });
  exportScenario('blindPursuitOld', function*(env, arg$) {
    var ref$,
        nTrials,
        ref1$,
        oddballRate,
        L,
        scene,
        screen,
        catcher,
        score,
        result,
        this$ = this;
    ref$ = arg$ != null ? arg$ : {}, nTrials = (ref1$ = ref$.nTrials) != null ? ref1$ : 50, oddballRate = (ref1$ = ref$.oddballRate) != null ? ref1$ : 1;
    L = env.L;
    this['let']('intro', {
      title: L("Catch the ball"),
      content: L('%blindPursuit.intro')
    });
    scene = new Scene;
    scene.preroll = function() {
      var n,
          t,
          i$,
          x$,
          ref$,
          len$;
      scene.tick(1 / 60);
      n = 100;
      t = Date.now();
      for (i$ = 0, len$ = (ref$ = (fn$())).length; i$ < len$; ++i$) {
        x$ = ref$[i$];
        scene.tick(1 / 60);
      }
      return console.log("Prewarming FPS", n / (Date.now() - t) * 1000);
      function fn$() {
        var i$,
            to$,
            results$ = [];
        for (i$ = 0, to$ = n; i$ <= to$; ++i$) {
          results$.push(i$);
        }
        return results$;
      }
    };
    screen = (yield assets.SceneDisplay());
    screen.object.position.z = -0.1;
    screen.object.scale.set(0.1, 0.1, 0.1);
    screen.object.visible = true;
    scene.visual.add(screen.object);
    catcher = new catchthething.SpatialCatch({
      oddballRate: oddballRate,
      controls: env.controls
    });
    scene.onTickHandled(function() {
      var objects,
          res$,
          i$,
          ref$,
          len$,
          obj,
          ref1$;
      res$ = [];
      for (i$ = 0, len$ = (ref$ = catcher.objects).length; i$ < len$; ++i$) {
        obj = ref$[i$];
        res$.push({
          id: obj.id,
          position: {
            x: (ref1$ = obj.mesh.position).x,
            y: ref1$.y,
            z: ref1$.z
          }
        });
      }
      objects = res$;
      return env.logger.write({
        sceneTime: scene.time,
        pursuitObjects: objects
      });
    });
    env.controls.change(function(btn, isOn) {
      if (btn === "catch" && isOn && screen.object.visible) {
        catcher['catch']();
      }
    });
    scene.onRender.add(function(dt) {
      catcher.tick(dt);
      return env.renderer.render(catcher.scene, catcher.camera, screen.renderTarget, true);
    });
    this['let']('scene', scene);
    (yield this.get('run'));
    score = {
      missed: 0,
      catched: 0,
      catchRate: function() {
        return this.catched / this.total();
      },
      total: function() {
        return this.catched + this.missed;
      }
    };
    catcher.objectAdded(function(obj) {
      return env.logger.write({pursuitObjectAdded: obj.id});
    });
    catcher.objectCatched(function(obj) {
      score.catched += 1;
      return env.logger.write({pursuitObjectCatched: obj.id});
    });
    catcher.objectMissed(function(obj) {
      score.missed += 1;
      return env.logger.write({pursuitObjectMissed: obj.id});
    });
    catcher.objectHandled(function() {
      var finalScore;
      if (score.total() < nTrials) {
        return;
      }
      finalScore = (score.catchRate() * 100).toFixed(1);
      return this$['let']('done', {
        passed: true,
        outro: {
          title: env.L("Level passed"),
          content: env.L("You caught " + finalScore + "% of the balls")
        }
      });
    });
    ui.gauge(env, {
      name: L("Catch percentage"),
      unit: L('%'),
      range: [0, 100],
      value: function() {
        return score.catchRate() * 100;
      },
      format: function(v) {
        return v.toFixed(1);
      }
    });
    result = (yield this.get('done'));
    return result;
  });
  exportScenario('blindPursuitOld2', function*(env, arg$) {
    var ref$,
        nRights,
        ref1$,
        oddballRate,
        x$,
        camera,
        scene,
        target,
        directions,
        rotations,
        targetDirection,
        getCurrentDirection,
        t,
        hideDuration,
        prevX,
        hideTime,
        fadeDuration,
        fadeTime,
        score,
        rightDirection,
        wrongDirection,
        this$ = this;
    ref$ = arg$ != null ? arg$ : {}, nRights = (ref1$ = ref$.nRights) != null ? ref1$ : 50, oddballRate = (ref1$ = ref$.oddballRate) != null ? ref1$ : 0.1;
    x$ = camera = new THREE.OrthographicCamera(-1, 1, -1, 1, 0.1, 10);
    x$.position.z = 5;
    env.onSize(function(w, h) {
      h = h / w;
      w = 1;
      camera.left = -w;
      camera.right = w;
      camera.bottom = -h;
      camera.top = h;
      return camera.updateProjectionMatrix();
    });
    scene = new Scene({camera: camera});
    scene.visual.add(new THREE.AmbientLight(0xffffff));
    target = (yield assets.ArrowMarker());
    target.position.set(0, 0, -1);
    target.visible = true;
    target.scale.set(0.08, 0.08, 0.08);
    directions = ['up', 'down'];
    rotations = {
      up: Math.PI,
      left: -(Math.PI / 2),
      right: Math.PI / 2,
      down: 0
    };
    targetDirection = 'down';
    getCurrentDirection = function() {
      var dirs,
          ref$,
          up,
          down,
          left,
          right,
          total,
          name,
          value;
      dirs = (ref$ = {
        up: (ref$ = env.controls).up,
        down: ref$.down,
        left: ref$.left,
        right: ref$.right
      }, up = ref$.up, down = ref$.down, left = ref$.left, right = ref$.right, ref$);
      total = up + down + left + right;
      if (total === 0 || total > 1) {
        return;
      }
      for (name in dirs) {
        value = dirs[name];
        if (value === 1) {
          return name;
        }
      }
    };
    scene.visual.add(target);
    scene.preroll = function() {};
    t = 0;
    hideDuration = 0.2;
    prevX = void 8;
    hideTime = 0;
    fadeDuration = 0.1;
    fadeTime = 0;
    score = {
      right: 0,
      wrong: 0,
      total: function() {
        return this.right - this.wrong;
      }
    };
    rightDirection = Signal();
    rightDirection(function() {
      return score.right += 1;
    });
    wrongDirection = Signal();
    wrongDirection(function() {
      return score.wrong += 1;
    });
    env.controls.change(function(key, isOn) {
      if (!isOn) {
        return;
      }
      if (key === targetDirection) {
        return rightDirection.dispatch();
      } else {
        return wrongDirection.dispatch();
      }
    });
    rightDirection(function() {
      var newdir;
      newdir = directions[Math.floor(Math.random() * directions.length)];
      targetDirection = newdir;
      target.rotation.z = rotations[targetDirection];
      return fadeTime = fadeDuration;
    });
    scene.beforeRender(function(dt) {
      var reactionTime,
          penaltyTime,
          cycleLength,
          pt,
          nthCycle,
          cycleRatio,
          dist,
          x;
      reactionTime = t / nRights;
      penaltyTime = (reactionTime * score.wrong) / nRights;
      if (score.total() >= nRights) {
        console.log(score);
        console.log(t);
        this$['let']('done', {
          passed: true,
          score: score,
          time: t,
          outro: {
            title: env.L("Round done!"),
            content: env.L("Average correct reaction time was " + reactionTime.toFixed(3) + " seconds. You made " + score.wrong + " errors, which cost about " + penaltyTime.toFixed(3) + " seconds.")
          }
        });
        return false;
      }
      if (score.right < 1) {
        return;
      }
      t += dt;
      cycleLength = 2;
      pt = t + cycleLength / 2.0;
      nthCycle = Math.floor(pt / cycleLength);
      cycleRatio = (pt % cycleLength) / cycleLength;
      if (nthCycle % 2 !== 0) {
        cycleRatio = 1 - cycleRatio;
      }
      dist = 0.5;
      target.position.x = x = (cycleRatio - 0.5) * 2 * dist;
      if (Math.sign(prevX) !== Math.sign(x) && hideTime <= 0) {
        hideTime = hideDuration;
        if (Math.random() < oddballRate) {
          t += Math.sign(Math.random() - 0.5) * (hideDuration * 0.5);
        }
      }
      prevX = x;
      hideTime -= dt;
      if (fadeTime > 0) {
        target.arrow.visible = false;
      } else {
        target.arrow.visible = true;
      }
      fadeTime -= dt;
      target.visible = !(hideTime > 0);
    });
    this['let']('scene', scene);
    (yield this.get('run'));
    return (yield this.get('done'));
  });
  exportScenario('blindPursuit', function*(env, arg$) {
    var ref$,
        duration,
        ref1$,
        oddballRate,
        x$,
        camera,
        scene,
        target,
        score,
        t,
        prevX,
        yPosition,
        ySpeed,
        distance,
        acceleration,
        hideDuration,
        showDuration,
        prevHide,
        hideTime,
        cycleLength,
        timeManipulation,
        timeWarp,
        gravity,
        mass,
        weightedError,
        errorWave,
        errorGain,
        totalError,
        prevHideCycle,
        this$ = this;
    ref$ = arg$ != null ? arg$ : {}, duration = (ref1$ = ref$.duration) != null ? ref1$ : 60.0 * 3, oddballRate = (ref1$ = ref$.oddballRate) != null ? ref1$ : 0.1;
    this['let']('intro', {
      title: env.L("Find the balance"),
      content: env.L("Use the steering wheel to keep the ball as close to the scale center as you can.")
    });
    x$ = camera = new THREE.OrthographicCamera(-1, 1, -1, 1, 0.1, 10);
    x$.position.z = 5;
    env.onSize(function(w, h) {
      w = w / h;
      h = 1;
      camera.left = -w;
      camera.right = w;
      camera.bottom = -h;
      camera.top = h;
      return camera.updateProjectionMatrix();
    });
    scene = new Scene({camera: camera});
    assets.addMarkerScreen(scene);
    scene.visual.add(new THREE.AmbientLight(0xffffff));
    target = (yield assets.BallBoard());
    target.position.set(0, 0, -1);
    target.visible = true;
    target.scale.set(0.5, 0.5, 0.5);
    scene.visual.add(target);
    scene.preroll = function() {};
    score = {
      right: 0,
      wrong: 0,
      total: function() {
        return this.right - this.wrong;
      }
    };
    env.controls.set({autocenter: 0.3});
    this['let']('scene', scene);
    t = 0;
    prevX = void 8;
    yPosition = 0.0;
    ySpeed = 0.0;
    distance = 0;
    acceleration = 0;
    hideDuration = 0.3;
    showDuration = 1.0;
    prevHide = 0.0;
    hideTime = 0;
    cycleLength = 1.3;
    timeManipulation = 0.5;
    timeWarp = cycleLength / 2.0;
    gravity = 5.0;
    mass = 10.0;
    weightedError = 1.0;
    errorWave = env.audioContext.createOscillator();
    errorWave.frequency.value = 1000;
    errorGain = env.audioContext.createGain();
    errorGain.gain.value = 0;
    errorWave.connect(errorGain);
    totalError = 0;
    prevHideCycle = void 8;
    scene.beforeRender(function(dt) {
      var meanError,
          relativeError,
          totalScore,
          angle,
          force,
          acceleration,
          error,
          relError,
          pt,
          nthCycle,
          cycleRatio,
          dist,
          prevTargetPos,
          rotSpeed,
          coeff,
          ref$;
      t += dt;
      if (t >= duration) {
        meanError = totalError / t;
        relativeError = meanError / 0.5;
        totalScore = (1 - relativeError) * 100;
        this$['let']('done', {
          passed: true,
          outro: {
            title: env.L("Round done!"),
            content: "Your score was " + totalScore.toFixed(1) + "%",
            totalScore: score
          }
        });
        return false;
      }
      angle = -env.controls.steering * Math.PI * 0.3;
      target.turnable.rotation.z = -angle;
      angle += (Math.random() - 0.5) * Math.PI * 0.1;
      force = mass * (gravity * Math.sin(angle));
      acceleration = force / mass;
      ySpeed += acceleration * dt;
      yPosition += ySpeed * dt;
      error = Math.abs(yPosition);
      totalError += dt * error;
      relError = error / 0.25;
      if (yPosition < -0.5 && ySpeed < 0) {
        yPosition = -0.5;
        ySpeed = 0;
      }
      if (yPosition > 0.5 && ySpeed > 0) {
        yPosition = 0.5;
        ySpeed = 0;
      }
      target.ball.position.x = yPosition;
      errorGain.gain.value = error;
      pt = t + timeWarp;
      nthCycle = Math.floor(pt / cycleLength);
      cycleRatio = (pt % cycleLength) / cycleLength;
      if (nthCycle % 2 !== 0) {
        cycleRatio = 1 - cycleRatio;
      }
      dist = 0.5;
      prevTargetPos = target.position.y;
      rotSpeed = 2.0;
      target.position.y = Math.sin(pt * rotSpeed) * dist;
      target.position.x = Math.cos(pt * rotSpeed) * dist;
      if (t - prevHide > showDuration) {
        prevHideCycle = nthCycle;
        prevHide = t;
        hideTime = hideDuration;
        if (Math.random() < oddballRate) {
          coeff = (Math.random() - 0.5) * 2;
          timeWarp += coeff * timeManipulation;
        }
      }
      hideTime -= dt;
      target.visible = !(hideTime > 0);
      env.logger.write({balancingTask: {
          time: t,
          timeWarp: timeWarp,
          ballPosition: {
            x: (ref$ = target.ball.position).x,
            y: ref$.y,
            z: ref$.z
          },
          ballVelocity: ySpeed,
          ballAcceleration: acceleration,
          visualRotation: target.turnable.rotation.z,
          trueRotation: angle,
          targetPosition: {
            x: (ref$ = target.position).x,
            y: ref$.y,
            z: ref$.z
          },
          targetVisible: target.visible
        }});
    });
    (yield this.get('run'));
    return (yield this.get('done'));
  });
  exportScenario('steeringCatcher', function*(env, arg$) {
    var ref$,
        duration,
        ref1$,
        oddballRate,
        x$,
        camera,
        width,
        height,
        margin,
        targetWidth,
        scene,
        geo,
        target,
        block,
        blockSpeed,
        speedup,
        slowdown,
        steeringSpeed,
        shineTime,
        hideDuration,
        showDuration,
        hideTime,
        prevHide,
        catched,
        missed,
        bias,
        t,
        this$ = this;
    ref$ = arg$ != null ? arg$ : {}, duration = (ref1$ = ref$.duration) != null ? ref1$ : 60.0 * 3, oddballRate = (ref1$ = ref$.oddballRate) != null ? ref1$ : 0.1;
    this['let']('intro', {
      title: env.L("Catch the blocks"),
      content: env.L("Use the steering wheel to catch the blocks.")
    });
    x$ = camera = new THREE.OrthographicCamera(-1, 1, -1, 1, 0.1, 10);
    x$.position.z = 5;
    width = 0.3;
    height = 0.6;
    margin = 0.0;
    targetWidth = 0.05;
    env.onSize(function(w, h) {
      w = w / h;
      h = 1;
      camera.left = -w;
      camera.right = w;
      camera.bottom = -h;
      camera.top = h;
      return camera.updateProjectionMatrix();
    });
    scene = new Scene({camera: camera});
    scene.preroll = function() {};
    assets.addMarkerScreen(scene);
    scene.visual.add(new THREE.AmbientLight(0xffffff));
    geo = new THREE.PlaneGeometry(targetWidth, 0.01);
    target = new THREE.Mesh(geo, new THREE.MeshBasicMaterial({
      color: 0xffffff,
      transparent: true
    }));
    target.position.y = -height;
    scene.visual.add(target);
    geo = new THREE.SphereGeometry(0.01, 32, 32);
    block = new THREE.Mesh(geo, new THREE.MeshBasicMaterial({color: 0xffffff}));
    block.position.y = height;
    scene.visual.add(block);
    blockSpeed = 0.7;
    speedup = 1.01;
    slowdown = 1.03;
    steeringSpeed = 2.0;
    shineTime = 0.1;
    hideDuration = 0.2;
    showDuration = 1.0;
    hideTime = 0;
    prevHide = 0;
    catched = 0;
    missed = 0;
    bias = 0;
    t = 0;
    scene.beforeRender(function(dt) {
      var totalScore,
          coeff,
          manipulation,
          ref$;
      t += dt;
      if (t >= duration) {
        totalScore = catched / (catched + missed) * 100;
        this$['let']('done', {
          passed: true,
          outro: {
            title: env.L("Round done!"),
            content: "Your score was " + totalScore.toFixed(1) + "%",
            totalScore: totalScore,
            finalSpeed: blockSpeed
          }
        });
        return false;
      }
      if (block.position.y < -height) {
        if (Math.abs(block.position.x) < targetWidth / 2.0) {
          blockSpeed *= speedup;
          target.shineLeft = shineTime;
          catched += 1;
        } else {
          blockSpeed /= slowdown;
          missed += 1;
        }
        block.position.y = height;
        bias = (Math.random() - 0.5) * 2 * (width - margin);
        env.logger.write({steeringCatcherBias: bias});
      }
      block.position.y -= dt * blockSpeed;
      block.position.x = env.controls.steering * 3 * width - bias;
      if (target.shineLeft > 0) {
        target.shineLeft -= dt;
        target.material.opacity = 1;
      } else {
        target.material.opacity = 0.5;
      }
      if (t - prevHide > showDuration) {
        prevHide = t;
        hideTime = hideDuration;
        if (Math.random() < oddballRate) {
          coeff = (Math.random() - 0.5) * 2;
          manipulation = (Math.random() - 0.5) * targetWidth * 2;
          env.logger.write({steeringCatcherManipulation: manipulation});
          bias += manipulation;
        }
      }
      hideTime -= dt;
      block.visible = !(hideTime > 0);
      env.logger.write({steeringCatcher: {
          time: t,
          ballPosition: {
            x: (ref$ = block.position).x,
            y: ref$.y,
            z: ref$.z
          },
          ballVelocity: blockSpeed,
          targetVisible: block.visible
        }});
    });
    env.controls.set({autocenter: 0.3});
    this['let']('scene', scene);
    (yield this.get('run'));
    return (yield this.get('done'));
  });
  shuffleArray = function(a) {
    var i,
        j,
        ref$;
    i = a.length;
    while (--i > 0) {
      j = Math.floor(Math.random() * (i + 1));
      ref$ = [a[j], a[i]], a[i] = ref$[0], a[j] = ref$[1];
    }
    return a;
  };
  exportScenario('pursuitDiscriminationPractice', function*(env) {
    var minFrequency,
        maxFrequency,
        steps,
        progress,
        controller,
        stepUp,
        stepDown,
        currentFrequency,
        trialsDone,
        reversalsNeeded,
        prevCorrect,
        reversals,
        staircase,
        base,
        result;
    minFrequency = 4;
    maxFrequency = 32;
    steps = [0.5, 0.3, 0.1, 0.05, 0.05, 0.05, 0.05, 0.05];
    progress = 0;
    controller = function(result) {
      result == null && (result = {});
      if (result.correct) {
        progress += 1;
      } else {
        progress -= 1;
      }
      progress = Math.max(progress, 0);
      if (progress >= steps.length) {
        controller = staircase;
        return controller(result);
      }
      return {
        frequency: minFrequency,
        targetDuration: steps[progress]
      };
    };
    stepUp = 1.05;
    stepDown = 1.2;
    currentFrequency = minFrequency;
    trialsDone = 0;
    reversalsNeeded = 10;
    prevCorrect = true;
    reversals = [];
    staircase = function(result) {
      trialsDone += 1;
      if (prevCorrect !== result.correct) {
        reversals.push(currentFrequency);
      }
      if (reversals.length >= reversalsNeeded) {
        return;
      }
      prevCorrect = result.correct;
      if (result.correct) {
        currentFrequency = Math.min(maxFrequency, currentFrequency * stepUp);
      } else {
        currentFrequency = Math.max(minFrequency, currentFrequency / stepDown);
      }
      return {frequency: currentFrequency};
    };
    base = pursuitDiscriminationBase(env, function() {
      var args,
          res$,
          i$,
          to$;
      res$ = [];
      for (i$ = 0, to$ = arguments.length; i$ < to$; ++i$) {
        res$.push(arguments[i$]);
      }
      args = res$;
      return controller.apply(null, args);
    });
    this['let']('intro', (yield base.get('intro')));
    this['let']('scene', (yield base.get('scene')));
    (yield this.get('run'));
    base['let']('run');
    result = (yield base.get('done'));
    this['let']('done');
    result.estimatedFrequency = reversals.reduce(curry$(function(x$, y$) {
      return x$ + y$;
    })) / reversals.length;
    env.logger.write({pursuitDiscriminationEstimatedFrequency: result.estimatedFrequency});
    console.log("Estimated frequency", result.estimatedFrequency);
    return result;
  });
  exportScenario('pursuitDiscrimination', function*(env, arg$) {
    var frequency,
        ref$,
        oddballs,
        ref1$,
        ref2$,
        totalTrials,
        standards,
        sequence,
        base,
        result;
    frequency = (ref$ = (arg$ != null ? arg$ : {}).frequency) != null ? ref$ : 10;
    oddballs = [ref$ = -0.1, 0.1, ref1$ = -0.25, 0.25, ref2$ = -0.4, 0.4, ref$, 0.1, ref1$, 0.25, ref2$, 0.4];
    totalTrials = Math.round(oddballs.length / 0.2);
    standards = repeatArray$([0.0], totalTrials - oddballs.length);
    sequence = shuffleArray(standards.concat(oddballs));
    sequence = [].concat([0.0, 0.0], sequence, [0.0, 0.0]);
    console.log("N trials", sequence.length);
    base = pursuitDiscriminationBase(env, function() {
      if (sequence.length === 0) {
        return;
      }
      return {
        manipulation: sequence.pop(),
        frequency: frequency
      };
    });
    this['let']('intro', (yield base.get('intro')));
    this['let']('scene', (yield base.get('scene')));
    (yield this.get('run'));
    base['let']('run');
    result = (yield base.get('done'));
    this['let']('done', result);
    return result;
  });
  pursuitDiscriminationBase = seqr.bind(function*(env, getParameters) {
    var defaultParameters,
        parameters,
        gratingLeft,
        gratingRight,
        introContent,
        x$,
        camera,
        scene,
        platform,
        target,
        t,
        score,
        oddballScore,
        ref$,
        pureScore,
        events,
        i$,
        schedule,
        trialResult,
        displacement,
        movementDirection,
        this$ = this;
    defaultParameters = {
      speed: 1.3,
      hideDuration: 0.3,
      cueDuration: 2.0,
      waitDuration: 2.0,
      maskDuration: 0.3,
      resultDuration: 2.0,
      targetDuration: 0.05,
      frequency: 10,
      manipulation: 0
    };
    parameters = import$(clone$(defaultParameters), getParameters());
    gratingLeft = assets.SineGratingBitmap({
      resolution: 256,
      cycles: parameters.frequency
    });
    gratingRight = assets.SineGratingBitmap({
      resolution: 256,
      cycles: parameters.frequency
    });
    introContent = $(env.L('%pursuitDiscrimination.intro'));
    gratingLeft = $(gratingLeft).css({
      width: '50%',
      height: 'auto',
      display: 'inline-block'
    }).css({transform: 'rotate(-45deg)'});
    gratingRight = $(gratingRight).css({
      width: '50%',
      height: 'auto',
      display: 'inline-block'
    }).css({transform: 'rotate(45deg)'});
    introContent.find('.leftStim').append(gratingLeft);
    introContent.find('.rightStim').append(gratingRight);
    this['let']('intro', {
      title: env.L("Find the direction"),
      content: introContent
    });
    x$ = camera = new THREE.OrthographicCamera(-1, 1, -1, 1, 0.1, 10);
    x$.position.z = 5;
    env.onSize(function(w, h) {
      w = w / h;
      h = 1;
      camera.left = -w;
      camera.right = w;
      camera.bottom = -h;
      camera.top = h;
      return camera.updateProjectionMatrix();
    });
    scene = new Scene({camera: camera});
    scene.preroll = function() {};
    assets.addMarkerScreen(scene);
    scene.visual.add(new THREE.AmbientLight(0xffffff));
    platform = new THREE.Object3D();
    scene.visual.add(platform);
    target = (yield assets.ArrowMarker());
    target.setFrequency(10);
    target.scale.set(0.3, 0.3, 0.3);
    target.signs.target.scale.set(0.3, 0.3, 0.3);
    platform.add(target);
    this['let']('scene', scene);
    t = 0;
    score = {
      correct: 0,
      incorrect: 0,
      percentage: function() {
        return this.correct / (this.correct + this.incorrect) * 100;
      },
      get total() {
        return this.correct + this.incorrect;
      }
    };
    oddballScore = (ref$ = clone$(score), ref$.correct = 0, ref$.incorrect = 0, ref$);
    pureScore = (ref$ = clone$(score), Object.defineProperty(ref$, 'correct', {
      get: function() {
        return score.correct - oddballScore.correct;
      },
      configurable: true,
      enumerable: true
    }), Object.defineProperty(ref$, 'incorrect', {
      get: function() {
        return score.incorrect - oddballScore.incorrect;
      },
      configurable: true,
      enumerable: true
    }), ref$);
    events = {
      begin: Signal(),
      hide: Signal(),
      show: Signal(),
      mask: Signal(),
      query: Signal(),
      wait: Signal(),
      result: Signal(),
      exit: Signal()
    };
    for (i$ in events) {
      (fn$.call(this, i$, events[i$]));
    }
    schedule = function(seconds, func) {
      var t;
      t = 0;
      return scene.beforeRender(function(dt) {
        if (t >= seconds) {
          func();
          return false;
        }
        t += dt;
      });
    };
    trialResult = void 8;
    events.begin(function() {
      trialResult = {};
      target.setFrequency(parameters.frequency);
      target.setSign('cue');
      schedule(parameters.cueDuration, bind$(events.hide, 'dispatch'));
    });
    events.hide(function() {
      platform.visible = false;
      schedule(parameters.hideDuration, bind$(events.show, 'dispatch'));
    });
    events.show(function() {
      target.signs.target.rotation.z = Math.sign(Math.random() - 0.5) * Math.PI / 4.0;
      platform.visible = true;
      target.setSign('target');
      schedule(parameters.targetDuration, bind$(events.mask, 'dispatch'));
      env.controls.change(function(key, isOn) {
        var keys,
            targetKey;
        if (!isOn) {
          return;
        }
        keys = ['left', 'right'];
        if (!in$(key, keys)) {
          return;
        }
        targetKey = keys[(target.signs.target.rotation.z < 0) * 1];
        trialResult.correct = key === targetKey;
        trialResult.targetKey = targetKey;
        trialResult.pressedKey = key;
        if (trialResult.correct) {
          score.correct += 1;
        } else {
          score.incorrect += 1;
        }
        if (parameters.manipulation !== 0) {
          if (trialResult.correct) {
            oddballScore.correct += 1;
          } else {
            oddballScore.incorrect += 1;
          }
        }
        env.logger.write({pursuitDiscriminationSummary: {
            time: t,
            parameters: parameters,
            result: trialResult
          }});
        schedule(0, bind$(events.wait, 'dispatch'));
        return false;
      });
    });
    events.mask(function() {
      if (trialResult.correct != null) {
        return;
      }
      target.setSign('mask');
      schedule(parameters.maskDuration, bind$(events.query, 'dispatch'));
    });
    events.query(function() {
      if (trialResult.correct != null) {
        return;
      }
      target.setSign('query');
    });
    events.wait(function() {
      target.setSign('wait');
      schedule(parameters.waitDuration, bind$(events.result, 'dispatch'));
    });
    events.result(function() {
      var params;
      console.log(parameters.manipulation, pureScore.percentage(), oddballScore.percentage());
      target.setSign(trialResult.correct ? 'success' : 'failure');
      params = getParameters(trialResult);
      if (params == null) {
        schedule(parameters.resultDuration, bind$(events.exit, 'dispatch')());
        return;
      }
      parameters = import$(clone$(defaultParameters), params);
      schedule(parameters.resultDuration, bind$(events.begin, 'dispatch'));
    });
    events.exit(function() {
      this$['let']('done', {
        score: score,
        outro: {
          title: env.L("Round done!"),
          content: env.L("You got " + score.percentage().toFixed(1) + "% right!")
        }
      });
    });
    displacement = 1.0;
    movementDirection = -1;
    events.begin(function() {
      var timeToCenter,
          startTime,
          hintTime;
      movementDirection *= -1;
      platform.position.x = (-movementDirection) * displacement;
      timeToCenter = displacement / parameters.speed;
      startTime = (parameters.cueDuration + parameters.hideDuration) - timeToCenter;
      hintTime = Math.max(0, startTime - 0.3);
      target.signs.cue.material.opacity = 0.5;
      target.signs.cue.material.needsUpdate = true;
      schedule(hintTime, function() {
        target.signs.cue.material.opacity = 1.0;
        return target.signs.cue.material.needsUpdate = true;
      });
      return schedule(startTime, function() {
        return scene.beforeRender(function(dt) {
          platform.position.x += dt * movementDirection * parameters.speed;
          if (platform.position.x * movementDirection >= displacement) {
            platform.position.x = movementDirection * displacement;
            return false;
          }
        });
      });
    });
    events.hide(function() {
      return platform.position.x += movementDirection * parameters.manipulation * parameters.speed;
    });
    events.begin.dispatch();
    scene.afterRender(function(dt) {
      var ref$;
      env.logger.write({pursuitDiscrimination: {
          platformPosition: {
            x: (ref$ = platform.position).x,
            y: ref$.y,
            z: ref$.z
          },
          targetRotation: target.signs.target.rotation.z
        }});
    });
    scene.afterRender(function(dt) {
      t += dt;
    });
    (yield this.get('run'));
    return (yield this.get('done'));
    function fn$(name, signal) {
      signal(function() {
        env.logger.write({pursuitDiscriminationState: {
            name: name,
            st: t
          }});
      });
    }
  });
  exportScenario('steerToTarget', function*(env, arg$) {
    var ref$,
        duration,
        ref1$,
        oddballRate,
        x$,
        camera,
        targetSize,
        targetDuration,
        circleRadius,
        cricleLength,
        angleSpan,
        targetRange,
        rotSpeed,
        rotRadius,
        hideDuration,
        showDuration,
        prevHide,
        hideTime,
        cycleLength,
        timeManipulation,
        timeWarp,
        scene,
        platform,
        geo,
        pointer,
        target,
        horizon,
        targetTimeLeft,
        slowdown,
        speedup,
        targetAngle,
        rotToAngle,
        t;
    ref$ = arg$ != null ? arg$ : {}, duration = (ref1$ = ref$.duration) != null ? ref1$ : 60.0, oddballRate = (ref1$ = ref$.oddballRate) != null ? ref1$ : 0.05;
    x$ = camera = new THREE.OrthographicCamera(-1, 1, -1, 1, 0.1, 10);
    x$.position.z = 5;
    targetSize = 0.03;
    targetDuration = 1.0;
    circleRadius = 0.1;
    cricleLength = circleRadius * 2 * Math.PI;
    angleSpan = (2 * targetSize) / circleRadius;
    targetRange = 0.4;
    rotSpeed = 2.0;
    rotRadius = 0.3;
    hideDuration = 0.3;
    showDuration = 1.0;
    prevHide = 0.0;
    hideTime = 0;
    cycleLength = 1.3;
    timeManipulation = 0.5;
    timeWarp = cycleLength / 2.0;
    env.onSize(function(w, h) {
      w = w / h;
      h = 1;
      camera.left = -w;
      camera.right = w;
      camera.bottom = -h;
      camera.top = h;
      return camera.updateProjectionMatrix();
    });
    scene = new Scene({camera: camera});
    scene.preroll = function() {};
    assets.addMarkerScreen(scene);
    scene.visual.add(new THREE.AmbientLight(0xffffff));
    platform = new THREE.Object3D();
    scene.visual.add(platform);
    geo = new THREE.SphereGeometry(targetSize, 32, 32);
    pointer = new THREE.Mesh(geo, new THREE.MeshBasicMaterial({
      color: 0xffffff,
      transparent: true,
      opacity: 0.5
    }));
    pointer.position.z = 0.1;
    geo = new THREE.SphereGeometry(targetSize / 2.0, 32, 32);
    target = new THREE.Mesh(geo, new THREE.MeshBasicMaterial({
      color: 0xffffff,
      transparent: true,
      opacity: 0.5
    }));
    platform.add(target);
    horizon = new THREE.Mesh(new THREE.PlaneGeometry(targetRange * 2, 0.01), new THREE.MeshBasicMaterial({
      color: 0xffffff,
      transparent: true,
      opacity: 0.5
    }));
    targetTimeLeft = 0.0;
    slowdown = 1.03;
    speedup = 1.01;
    targetAngle = targetRange / 2.0;
    rotToAngle = function(obj, angle) {
      return obj.position.x = Math.sin(angle) * circleRadius;
    };
    t = 0;
    scene.beforeRender(function(dt) {
      var pt,
          period,
          targetPeriod,
          coeff;
      t += dt;
      pt = t + timeWarp;
      period = 1 / 2.0;
      platform.position.x = Math.cos(pt / period) * rotRadius;
      platform.position.y = Math.sin(pt / period) * rotRadius;
      targetPeriod = 0.5;
      if (t - prevHide > showDuration) {
        prevHide = t;
        hideTime = hideDuration;
        if (Math.random() < oddballRate) {
          coeff = (Math.random() - 0.5) * 2;
          timeWarp += coeff * timeManipulation;
        }
      }
      hideTime -= dt;
      platform.visible = !(hideTime > 0);
    });
    env.controls.set({autocenter: 0.0});
    this['let']('scene', scene);
    (yield this.get('run'));
    return (yield this.get('done'));
  });
  exportScenario('vsyncTest', function*(env) {
    var x$,
        camera,
        scene,
        geo,
        cyan,
        red,
        i;
    x$ = camera = new THREE.OrthographicCamera(-1, 1, -1, 1, 0.1, 10);
    x$.position.z = 5;
    env.onSize(function(w, h) {
      w = w / h;
      h = 1;
      camera.left = -w;
      camera.right = w;
      camera.bottom = -h;
      camera.top = h;
      return camera.updateProjectionMatrix();
    });
    scene = new Scene({camera: camera});
    scene.preroll = function() {};
    geo = new THREE.SphereGeometry(0.3, 32, 32);
    cyan = new THREE.Mesh(geo, new THREE.MeshBasicMaterial({color: 0x00ffff}));
    red = new THREE.Mesh(geo, new THREE.MeshBasicMaterial({color: 0xff0000}));
    scene.visual.add(cyan);
    scene.visual.add(red);
    i = 0;
    scene.beforeRender(function(dt) {
      i += 1;
      if (i % 2 === 0) {
        cyan.visible = true;
        red.visible = false;
      } else {
        cyan.visible = false;
        red.visible = true;
      }
    });
    this['let']('scene', scene);
    (yield this.get('run'));
    return (yield this.get('done'));
  });
  exportScenario('soundSpook', function*(env, arg$) {
    var ref$,
        preIntro,
        ref1$,
        spookRate,
        duration,
        preSilence,
        postSilence,
        bell,
        noise,
        nBursts,
        times,
        res$,
        i$,
        i,
        schedule,
        to$,
        msg,
        len$,
        pause;
    ref$ = arg$ != null ? arg$ : {}, preIntro = (ref1$ = ref$.preIntro) != null ? ref1$ : false, spookRate = (ref1$ = ref$.spookRate) != null ? ref1$ : 1 / 20.0, duration = (ref1$ = ref$.duration) != null ? ref1$ : 90.0, preSilence = (ref1$ = ref$.preSilence) != null ? ref1$ : 30.0, postSilence = (ref1$ = ref$.postSilence) != null ? ref1$ : 20.0;
    bell = (yield BellPlayer(env));
    noise = (yield NoisePlayer(env));
    nBursts = Math.round(duration * spookRate);
    res$ = [];
    for (i$ = 0; i$ <= nBursts; ++i$) {
      i = i$;
      res$.push(Math.random() * duration);
    }
    times = res$;
    times = prelude.sort(times);
    schedule = [times[0]];
    for (i$ = 1, to$ = times.length; i$ < to$; ++i$) {
      i = i$;
      schedule.push(times[i] - times[i - 1]);
    }
    if (preIntro) {
      (yield ui.instructionScreen(env, function() {
        this('title').append(env.L("Relaxation and sound response"));
        this('subtitle').append(env.L("Notification sound"));
        this('content').append(env.L("%soundSpook.notificationSound"));
        return this('accept').text(env.L("Play the notification sound"));
      }));
      (yield bell());
      (yield ui.instructionScreen(env, function() {
        this('title').append(env.L("Relaxation and sound response"));
        this('subtitle').append(env.L("Noise sound"));
        this('content').append(env.L('%soundSpook.noiseSound'));
        "During the relaxation periods, a noise sound is occasionally played.\nThis is used to measure how your nervous system responses to sudden events.\nPlease try not to move when you hear the sound even if you get surprised,\nand keep your eyes closed.";
        return this('accept').text(env.L("Play the noise sound"));
      }));
      (yield noise());
    }
    (yield ui.instructionScreen(env, function() {
      this('title').append(env.L("Relaxation and sound response"));
      return this('content').append(env.L('%soundSpook.instruction'));
    }));
    msg = $('<h1>').text(env.L("Please keep your eyes closed")).css({
      "text-align": "center",
      "margin-top": "10%"
    });
    env.container.append(msg);
    (yield bell());
    env.logger.write({soundSpookEvent: "preSilenceStart"});
    (yield ui.sleep(preSilence));
    env.logger.write({soundSpookEvent: "preSilenceDone"});
    for (i$ = 0, len$ = schedule.length; i$ < len$; ++i$) {
      pause = schedule[i$];
      (yield ui.sleep(pause));
      env.logger.write({soundSpookEvent: "noiseBurst"});
      noise();
    }
    env.logger.write({soundSpookEvent: "postSilenceStart"});
    (yield ui.sleep(postSilence));
    env.logger.write({soundSpookEvent: "postSilenceDone"});
    return (yield bell());
  });
  function clone$(it) {
    function fun() {}
    fun.prototype = it;
    return new fun;
  }
  function bind$(obj, key, target) {
    return function() {
      return (target || obj)[key].apply(obj, arguments);
    };
  }
  function curry$(f, bound) {
    var context,
        _curry = function(args) {
          return f.length > 1 ? function() {
            var params = args ? args.concat() : [];
            context = bound ? context || this : this;
            return params.push.apply(params, arguments) < f.length && arguments.length ? _curry.call(context, params) : f.apply(context, params);
          } : f;
        };
    return _curry();
  }
  function repeatArray$(arr, n) {
    for (var r = []; n > 0; (n >>= 1) && (arr = arr.concat(arr)))
      if (n & 1)
        r.push.apply(r, arr);
    return r;
  }
  function import$(obj, src) {
    var own = {}.hasOwnProperty;
    for (var key in src)
      if (own.call(src, key))
        obj[key] = src[key];
    return obj;
  }
  function in$(x, xs) {
    var i = -1,
        l = xs.length >>> 0;
    while (++i < l)
      if (x === xs[i])
        return true;
    return false;
  }
  return module.exports;
});

(function() {
var define = $__System.amdDefine;
(function(global, factory) {
  if (typeof module === "object" && typeof module.exports === "object") {
    module.exports = global.document ? factory(global, true) : function(w) {
      if (!w.document) {
        throw new Error("jQuery requires a window with a document");
      }
      return factory(w);
    };
  } else {
    factory(global);
  }
}(typeof window !== "undefined" ? window : this, function(window, noGlobal) {
  var arr = [];
  var slice = arr.slice;
  var concat = arr.concat;
  var push = arr.push;
  var indexOf = arr.indexOf;
  var class2type = {};
  var toString = class2type.toString;
  var hasOwn = class2type.hasOwnProperty;
  var support = {};
  var document = window.document,
      version = "2.1.4",
      jQuery = function(selector, context) {
        return new jQuery.fn.init(selector, context);
      },
      rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
      rmsPrefix = /^-ms-/,
      rdashAlpha = /-([\da-z])/gi,
      fcamelCase = function(all, letter) {
        return letter.toUpperCase();
      };
  jQuery.fn = jQuery.prototype = {
    jquery: version,
    constructor: jQuery,
    selector: "",
    length: 0,
    toArray: function() {
      return slice.call(this);
    },
    get: function(num) {
      return num != null ? (num < 0 ? this[num + this.length] : this[num]) : slice.call(this);
    },
    pushStack: function(elems) {
      var ret = jQuery.merge(this.constructor(), elems);
      ret.prevObject = this;
      ret.context = this.context;
      return ret;
    },
    each: function(callback, args) {
      return jQuery.each(this, callback, args);
    },
    map: function(callback) {
      return this.pushStack(jQuery.map(this, function(elem, i) {
        return callback.call(elem, i, elem);
      }));
    },
    slice: function() {
      return this.pushStack(slice.apply(this, arguments));
    },
    first: function() {
      return this.eq(0);
    },
    last: function() {
      return this.eq(-1);
    },
    eq: function(i) {
      var len = this.length,
          j = +i + (i < 0 ? len : 0);
      return this.pushStack(j >= 0 && j < len ? [this[j]] : []);
    },
    end: function() {
      return this.prevObject || this.constructor(null);
    },
    push: push,
    sort: arr.sort,
    splice: arr.splice
  };
  jQuery.extend = jQuery.fn.extend = function() {
    var options,
        name,
        src,
        copy,
        copyIsArray,
        clone,
        target = arguments[0] || {},
        i = 1,
        length = arguments.length,
        deep = false;
    if (typeof target === "boolean") {
      deep = target;
      target = arguments[i] || {};
      i++;
    }
    if (typeof target !== "object" && !jQuery.isFunction(target)) {
      target = {};
    }
    if (i === length) {
      target = this;
      i--;
    }
    for (; i < length; i++) {
      if ((options = arguments[i]) != null) {
        for (name in options) {
          src = target[name];
          copy = options[name];
          if (target === copy) {
            continue;
          }
          if (deep && copy && (jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)))) {
            if (copyIsArray) {
              copyIsArray = false;
              clone = src && jQuery.isArray(src) ? src : [];
            } else {
              clone = src && jQuery.isPlainObject(src) ? src : {};
            }
            target[name] = jQuery.extend(deep, clone, copy);
          } else if (copy !== undefined) {
            target[name] = copy;
          }
        }
      }
    }
    return target;
  };
  jQuery.extend({
    expando: "jQuery" + (version + Math.random()).replace(/\D/g, ""),
    isReady: true,
    error: function(msg) {
      throw new Error(msg);
    },
    noop: function() {},
    isFunction: function(obj) {
      return jQuery.type(obj) === "function";
    },
    isArray: Array.isArray,
    isWindow: function(obj) {
      return obj != null && obj === obj.window;
    },
    isNumeric: function(obj) {
      return !jQuery.isArray(obj) && (obj - parseFloat(obj) + 1) >= 0;
    },
    isPlainObject: function(obj) {
      if (jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow(obj)) {
        return false;
      }
      if (obj.constructor && !hasOwn.call(obj.constructor.prototype, "isPrototypeOf")) {
        return false;
      }
      return true;
    },
    isEmptyObject: function(obj) {
      var name;
      for (name in obj) {
        return false;
      }
      return true;
    },
    type: function(obj) {
      if (obj == null) {
        return obj + "";
      }
      return typeof obj === "object" || typeof obj === "function" ? class2type[toString.call(obj)] || "object" : typeof obj;
    },
    globalEval: function(code) {
      var script,
          indirect = eval;
      code = jQuery.trim(code);
      if (code) {
        if (code.indexOf("use strict") === 1) {
          script = document.createElement("script");
          script.text = code;
          document.head.appendChild(script).parentNode.removeChild(script);
        } else {
          indirect(code);
        }
      }
    },
    camelCase: function(string) {
      return string.replace(rmsPrefix, "ms-").replace(rdashAlpha, fcamelCase);
    },
    nodeName: function(elem, name) {
      return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
    },
    each: function(obj, callback, args) {
      var value,
          i = 0,
          length = obj.length,
          isArray = isArraylike(obj);
      if (args) {
        if (isArray) {
          for (; i < length; i++) {
            value = callback.apply(obj[i], args);
            if (value === false) {
              break;
            }
          }
        } else {
          for (i in obj) {
            value = callback.apply(obj[i], args);
            if (value === false) {
              break;
            }
          }
        }
      } else {
        if (isArray) {
          for (; i < length; i++) {
            value = callback.call(obj[i], i, obj[i]);
            if (value === false) {
              break;
            }
          }
        } else {
          for (i in obj) {
            value = callback.call(obj[i], i, obj[i]);
            if (value === false) {
              break;
            }
          }
        }
      }
      return obj;
    },
    trim: function(text) {
      return text == null ? "" : (text + "").replace(rtrim, "");
    },
    makeArray: function(arr, results) {
      var ret = results || [];
      if (arr != null) {
        if (isArraylike(Object(arr))) {
          jQuery.merge(ret, typeof arr === "string" ? [arr] : arr);
        } else {
          push.call(ret, arr);
        }
      }
      return ret;
    },
    inArray: function(elem, arr, i) {
      return arr == null ? -1 : indexOf.call(arr, elem, i);
    },
    merge: function(first, second) {
      var len = +second.length,
          j = 0,
          i = first.length;
      for (; j < len; j++) {
        first[i++] = second[j];
      }
      first.length = i;
      return first;
    },
    grep: function(elems, callback, invert) {
      var callbackInverse,
          matches = [],
          i = 0,
          length = elems.length,
          callbackExpect = !invert;
      for (; i < length; i++) {
        callbackInverse = !callback(elems[i], i);
        if (callbackInverse !== callbackExpect) {
          matches.push(elems[i]);
        }
      }
      return matches;
    },
    map: function(elems, callback, arg) {
      var value,
          i = 0,
          length = elems.length,
          isArray = isArraylike(elems),
          ret = [];
      if (isArray) {
        for (; i < length; i++) {
          value = callback(elems[i], i, arg);
          if (value != null) {
            ret.push(value);
          }
        }
      } else {
        for (i in elems) {
          value = callback(elems[i], i, arg);
          if (value != null) {
            ret.push(value);
          }
        }
      }
      return concat.apply([], ret);
    },
    guid: 1,
    proxy: function(fn, context) {
      var tmp,
          args,
          proxy;
      if (typeof context === "string") {
        tmp = fn[context];
        context = fn;
        fn = tmp;
      }
      if (!jQuery.isFunction(fn)) {
        return undefined;
      }
      args = slice.call(arguments, 2);
      proxy = function() {
        return fn.apply(context || this, args.concat(slice.call(arguments)));
      };
      proxy.guid = fn.guid = fn.guid || jQuery.guid++;
      return proxy;
    },
    now: Date.now,
    support: support
  });
  jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
    class2type["[object " + name + "]"] = name.toLowerCase();
  });
  function isArraylike(obj) {
    var length = "length" in obj && obj.length,
        type = jQuery.type(obj);
    if (type === "function" || jQuery.isWindow(obj)) {
      return false;
    }
    if (obj.nodeType === 1 && length) {
      return true;
    }
    return type === "array" || length === 0 || typeof length === "number" && length > 0 && (length - 1) in obj;
  }
  var Sizzle = (function(window) {
    var i,
        support,
        Expr,
        getText,
        isXML,
        tokenize,
        compile,
        select,
        outermostContext,
        sortInput,
        hasDuplicate,
        setDocument,
        document,
        docElem,
        documentIsHTML,
        rbuggyQSA,
        rbuggyMatches,
        matches,
        contains,
        expando = "sizzle" + 1 * new Date(),
        preferredDoc = window.document,
        dirruns = 0,
        done = 0,
        classCache = createCache(),
        tokenCache = createCache(),
        compilerCache = createCache(),
        sortOrder = function(a, b) {
          if (a === b) {
            hasDuplicate = true;
          }
          return 0;
        },
        MAX_NEGATIVE = 1 << 31,
        hasOwn = ({}).hasOwnProperty,
        arr = [],
        pop = arr.pop,
        push_native = arr.push,
        push = arr.push,
        slice = arr.slice,
        indexOf = function(list, elem) {
          var i = 0,
              len = list.length;
          for (; i < len; i++) {
            if (list[i] === elem) {
              return i;
            }
          }
          return -1;
        },
        booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
        whitespace = "[\\x20\\t\\r\\n\\f]",
        characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
        identifier = characterEncoding.replace("w", "w#"),
        attributes = "\\[" + whitespace + "*(" + characterEncoding + ")(?:" + whitespace + "*([*^$|!~]?=)" + whitespace + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + "*\\]",
        pseudos = ":(" + characterEncoding + ")(?:\\((" + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + ".*" + ")\\)|)",
        rwhitespace = new RegExp(whitespace + "+", "g"),
        rtrim = new RegExp("^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g"),
        rcomma = new RegExp("^" + whitespace + "*," + whitespace + "*"),
        rcombinators = new RegExp("^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*"),
        rattributeQuotes = new RegExp("=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g"),
        rpseudo = new RegExp(pseudos),
        ridentifier = new RegExp("^" + identifier + "$"),
        matchExpr = {
          "ID": new RegExp("^#(" + characterEncoding + ")"),
          "CLASS": new RegExp("^\\.(" + characterEncoding + ")"),
          "TAG": new RegExp("^(" + characterEncoding.replace("w", "w*") + ")"),
          "ATTR": new RegExp("^" + attributes),
          "PSEUDO": new RegExp("^" + pseudos),
          "CHILD": new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i"),
          "bool": new RegExp("^(?:" + booleans + ")$", "i"),
          "needsContext": new RegExp("^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i")
        },
        rinputs = /^(?:input|select|textarea|button)$/i,
        rheader = /^h\d$/i,
        rnative = /^[^{]+\{\s*\[native \w/,
        rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
        rsibling = /[+~]/,
        rescape = /'|\\/g,
        runescape = new RegExp("\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig"),
        funescape = function(_, escaped, escapedWhitespace) {
          var high = "0x" + escaped - 0x10000;
          return high !== high || escapedWhitespace ? escaped : high < 0 ? String.fromCharCode(high + 0x10000) : String.fromCharCode(high >> 10 | 0xD800, high & 0x3FF | 0xDC00);
        },
        unloadHandler = function() {
          setDocument();
        };
    try {
      push.apply((arr = slice.call(preferredDoc.childNodes)), preferredDoc.childNodes);
      arr[preferredDoc.childNodes.length].nodeType;
    } catch (e) {
      push = {apply: arr.length ? function(target, els) {
          push_native.apply(target, slice.call(els));
        } : function(target, els) {
          var j = target.length,
              i = 0;
          while ((target[j++] = els[i++])) {}
          target.length = j - 1;
        }};
    }
    function Sizzle(selector, context, results, seed) {
      var match,
          elem,
          m,
          nodeType,
          i,
          groups,
          old,
          nid,
          newContext,
          newSelector;
      if ((context ? context.ownerDocument || context : preferredDoc) !== document) {
        setDocument(context);
      }
      context = context || document;
      results = results || [];
      nodeType = context.nodeType;
      if (typeof selector !== "string" || !selector || nodeType !== 1 && nodeType !== 9 && nodeType !== 11) {
        return results;
      }
      if (!seed && documentIsHTML) {
        if (nodeType !== 11 && (match = rquickExpr.exec(selector))) {
          if ((m = match[1])) {
            if (nodeType === 9) {
              elem = context.getElementById(m);
              if (elem && elem.parentNode) {
                if (elem.id === m) {
                  results.push(elem);
                  return results;
                }
              } else {
                return results;
              }
            } else {
              if (context.ownerDocument && (elem = context.ownerDocument.getElementById(m)) && contains(context, elem) && elem.id === m) {
                results.push(elem);
                return results;
              }
            }
          } else if (match[2]) {
            push.apply(results, context.getElementsByTagName(selector));
            return results;
          } else if ((m = match[3]) && support.getElementsByClassName) {
            push.apply(results, context.getElementsByClassName(m));
            return results;
          }
        }
        if (support.qsa && (!rbuggyQSA || !rbuggyQSA.test(selector))) {
          nid = old = expando;
          newContext = context;
          newSelector = nodeType !== 1 && selector;
          if (nodeType === 1 && context.nodeName.toLowerCase() !== "object") {
            groups = tokenize(selector);
            if ((old = context.getAttribute("id"))) {
              nid = old.replace(rescape, "\\$&");
            } else {
              context.setAttribute("id", nid);
            }
            nid = "[id='" + nid + "'] ";
            i = groups.length;
            while (i--) {
              groups[i] = nid + toSelector(groups[i]);
            }
            newContext = rsibling.test(selector) && testContext(context.parentNode) || context;
            newSelector = groups.join(",");
          }
          if (newSelector) {
            try {
              push.apply(results, newContext.querySelectorAll(newSelector));
              return results;
            } catch (qsaError) {} finally {
              if (!old) {
                context.removeAttribute("id");
              }
            }
          }
        }
      }
      return select(selector.replace(rtrim, "$1"), context, results, seed);
    }
    function createCache() {
      var keys = [];
      function cache(key, value) {
        if (keys.push(key + " ") > Expr.cacheLength) {
          delete cache[keys.shift()];
        }
        return (cache[key + " "] = value);
      }
      return cache;
    }
    function markFunction(fn) {
      fn[expando] = true;
      return fn;
    }
    function assert(fn) {
      var div = document.createElement("div");
      try {
        return !!fn(div);
      } catch (e) {
        return false;
      } finally {
        if (div.parentNode) {
          div.parentNode.removeChild(div);
        }
        div = null;
      }
    }
    function addHandle(attrs, handler) {
      var arr = attrs.split("|"),
          i = attrs.length;
      while (i--) {
        Expr.attrHandle[arr[i]] = handler;
      }
    }
    function siblingCheck(a, b) {
      var cur = b && a,
          diff = cur && a.nodeType === 1 && b.nodeType === 1 && (~b.sourceIndex || MAX_NEGATIVE) - (~a.sourceIndex || MAX_NEGATIVE);
      if (diff) {
        return diff;
      }
      if (cur) {
        while ((cur = cur.nextSibling)) {
          if (cur === b) {
            return -1;
          }
        }
      }
      return a ? 1 : -1;
    }
    function createInputPseudo(type) {
      return function(elem) {
        var name = elem.nodeName.toLowerCase();
        return name === "input" && elem.type === type;
      };
    }
    function createButtonPseudo(type) {
      return function(elem) {
        var name = elem.nodeName.toLowerCase();
        return (name === "input" || name === "button") && elem.type === type;
      };
    }
    function createPositionalPseudo(fn) {
      return markFunction(function(argument) {
        argument = +argument;
        return markFunction(function(seed, matches) {
          var j,
              matchIndexes = fn([], seed.length, argument),
              i = matchIndexes.length;
          while (i--) {
            if (seed[(j = matchIndexes[i])]) {
              seed[j] = !(matches[j] = seed[j]);
            }
          }
        });
      });
    }
    function testContext(context) {
      return context && typeof context.getElementsByTagName !== "undefined" && context;
    }
    support = Sizzle.support = {};
    isXML = Sizzle.isXML = function(elem) {
      var documentElement = elem && (elem.ownerDocument || elem).documentElement;
      return documentElement ? documentElement.nodeName !== "HTML" : false;
    };
    setDocument = Sizzle.setDocument = function(node) {
      var hasCompare,
          parent,
          doc = node ? node.ownerDocument || node : preferredDoc;
      if (doc === document || doc.nodeType !== 9 || !doc.documentElement) {
        return document;
      }
      document = doc;
      docElem = doc.documentElement;
      parent = doc.defaultView;
      if (parent && parent !== parent.top) {
        if (parent.addEventListener) {
          parent.addEventListener("unload", unloadHandler, false);
        } else if (parent.attachEvent) {
          parent.attachEvent("onunload", unloadHandler);
        }
      }
      documentIsHTML = !isXML(doc);
      support.attributes = assert(function(div) {
        div.className = "i";
        return !div.getAttribute("className");
      });
      support.getElementsByTagName = assert(function(div) {
        div.appendChild(doc.createComment(""));
        return !div.getElementsByTagName("*").length;
      });
      support.getElementsByClassName = rnative.test(doc.getElementsByClassName);
      support.getById = assert(function(div) {
        docElem.appendChild(div).id = expando;
        return !doc.getElementsByName || !doc.getElementsByName(expando).length;
      });
      if (support.getById) {
        Expr.find["ID"] = function(id, context) {
          if (typeof context.getElementById !== "undefined" && documentIsHTML) {
            var m = context.getElementById(id);
            return m && m.parentNode ? [m] : [];
          }
        };
        Expr.filter["ID"] = function(id) {
          var attrId = id.replace(runescape, funescape);
          return function(elem) {
            return elem.getAttribute("id") === attrId;
          };
        };
      } else {
        delete Expr.find["ID"];
        Expr.filter["ID"] = function(id) {
          var attrId = id.replace(runescape, funescape);
          return function(elem) {
            var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
            return node && node.value === attrId;
          };
        };
      }
      Expr.find["TAG"] = support.getElementsByTagName ? function(tag, context) {
        if (typeof context.getElementsByTagName !== "undefined") {
          return context.getElementsByTagName(tag);
        } else if (support.qsa) {
          return context.querySelectorAll(tag);
        }
      } : function(tag, context) {
        var elem,
            tmp = [],
            i = 0,
            results = context.getElementsByTagName(tag);
        if (tag === "*") {
          while ((elem = results[i++])) {
            if (elem.nodeType === 1) {
              tmp.push(elem);
            }
          }
          return tmp;
        }
        return results;
      };
      Expr.find["CLASS"] = support.getElementsByClassName && function(className, context) {
        if (documentIsHTML) {
          return context.getElementsByClassName(className);
        }
      };
      rbuggyMatches = [];
      rbuggyQSA = [];
      if ((support.qsa = rnative.test(doc.querySelectorAll))) {
        assert(function(div) {
          docElem.appendChild(div).innerHTML = "<a id='" + expando + "'></a>" + "<select id='" + expando + "-\f]' msallowcapture=''>" + "<option selected=''></option></select>";
          if (div.querySelectorAll("[msallowcapture^='']").length) {
            rbuggyQSA.push("[*^$]=" + whitespace + "*(?:''|\"\")");
          }
          if (!div.querySelectorAll("[selected]").length) {
            rbuggyQSA.push("\\[" + whitespace + "*(?:value|" + booleans + ")");
          }
          if (!div.querySelectorAll("[id~=" + expando + "-]").length) {
            rbuggyQSA.push("~=");
          }
          if (!div.querySelectorAll(":checked").length) {
            rbuggyQSA.push(":checked");
          }
          if (!div.querySelectorAll("a#" + expando + "+*").length) {
            rbuggyQSA.push(".#.+[+~]");
          }
        });
        assert(function(div) {
          var input = doc.createElement("input");
          input.setAttribute("type", "hidden");
          div.appendChild(input).setAttribute("name", "D");
          if (div.querySelectorAll("[name=d]").length) {
            rbuggyQSA.push("name" + whitespace + "*[*^$|!~]?=");
          }
          if (!div.querySelectorAll(":enabled").length) {
            rbuggyQSA.push(":enabled", ":disabled");
          }
          div.querySelectorAll("*,:x");
          rbuggyQSA.push(",.*:");
        });
      }
      if ((support.matchesSelector = rnative.test((matches = docElem.matches || docElem.webkitMatchesSelector || docElem.mozMatchesSelector || docElem.oMatchesSelector || docElem.msMatchesSelector)))) {
        assert(function(div) {
          support.disconnectedMatch = matches.call(div, "div");
          matches.call(div, "[s!='']:x");
          rbuggyMatches.push("!=", pseudos);
        });
      }
      rbuggyQSA = rbuggyQSA.length && new RegExp(rbuggyQSA.join("|"));
      rbuggyMatches = rbuggyMatches.length && new RegExp(rbuggyMatches.join("|"));
      hasCompare = rnative.test(docElem.compareDocumentPosition);
      contains = hasCompare || rnative.test(docElem.contains) ? function(a, b) {
        var adown = a.nodeType === 9 ? a.documentElement : a,
            bup = b && b.parentNode;
        return a === bup || !!(bup && bup.nodeType === 1 && (adown.contains ? adown.contains(bup) : a.compareDocumentPosition && a.compareDocumentPosition(bup) & 16));
      } : function(a, b) {
        if (b) {
          while ((b = b.parentNode)) {
            if (b === a) {
              return true;
            }
          }
        }
        return false;
      };
      sortOrder = hasCompare ? function(a, b) {
        if (a === b) {
          hasDuplicate = true;
          return 0;
        }
        var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
        if (compare) {
          return compare;
        }
        compare = (a.ownerDocument || a) === (b.ownerDocument || b) ? a.compareDocumentPosition(b) : 1;
        if (compare & 1 || (!support.sortDetached && b.compareDocumentPosition(a) === compare)) {
          if (a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a)) {
            return -1;
          }
          if (b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b)) {
            return 1;
          }
          return sortInput ? (indexOf(sortInput, a) - indexOf(sortInput, b)) : 0;
        }
        return compare & 4 ? -1 : 1;
      } : function(a, b) {
        if (a === b) {
          hasDuplicate = true;
          return 0;
        }
        var cur,
            i = 0,
            aup = a.parentNode,
            bup = b.parentNode,
            ap = [a],
            bp = [b];
        if (!aup || !bup) {
          return a === doc ? -1 : b === doc ? 1 : aup ? -1 : bup ? 1 : sortInput ? (indexOf(sortInput, a) - indexOf(sortInput, b)) : 0;
        } else if (aup === bup) {
          return siblingCheck(a, b);
        }
        cur = a;
        while ((cur = cur.parentNode)) {
          ap.unshift(cur);
        }
        cur = b;
        while ((cur = cur.parentNode)) {
          bp.unshift(cur);
        }
        while (ap[i] === bp[i]) {
          i++;
        }
        return i ? siblingCheck(ap[i], bp[i]) : ap[i] === preferredDoc ? -1 : bp[i] === preferredDoc ? 1 : 0;
      };
      return doc;
    };
    Sizzle.matches = function(expr, elements) {
      return Sizzle(expr, null, null, elements);
    };
    Sizzle.matchesSelector = function(elem, expr) {
      if ((elem.ownerDocument || elem) !== document) {
        setDocument(elem);
      }
      expr = expr.replace(rattributeQuotes, "='$1']");
      if (support.matchesSelector && documentIsHTML && (!rbuggyMatches || !rbuggyMatches.test(expr)) && (!rbuggyQSA || !rbuggyQSA.test(expr))) {
        try {
          var ret = matches.call(elem, expr);
          if (ret || support.disconnectedMatch || elem.document && elem.document.nodeType !== 11) {
            return ret;
          }
        } catch (e) {}
      }
      return Sizzle(expr, document, null, [elem]).length > 0;
    };
    Sizzle.contains = function(context, elem) {
      if ((context.ownerDocument || context) !== document) {
        setDocument(context);
      }
      return contains(context, elem);
    };
    Sizzle.attr = function(elem, name) {
      if ((elem.ownerDocument || elem) !== document) {
        setDocument(elem);
      }
      var fn = Expr.attrHandle[name.toLowerCase()],
          val = fn && hasOwn.call(Expr.attrHandle, name.toLowerCase()) ? fn(elem, name, !documentIsHTML) : undefined;
      return val !== undefined ? val : support.attributes || !documentIsHTML ? elem.getAttribute(name) : (val = elem.getAttributeNode(name)) && val.specified ? val.value : null;
    };
    Sizzle.error = function(msg) {
      throw new Error("Syntax error, unrecognized expression: " + msg);
    };
    Sizzle.uniqueSort = function(results) {
      var elem,
          duplicates = [],
          j = 0,
          i = 0;
      hasDuplicate = !support.detectDuplicates;
      sortInput = !support.sortStable && results.slice(0);
      results.sort(sortOrder);
      if (hasDuplicate) {
        while ((elem = results[i++])) {
          if (elem === results[i]) {
            j = duplicates.push(i);
          }
        }
        while (j--) {
          results.splice(duplicates[j], 1);
        }
      }
      sortInput = null;
      return results;
    };
    getText = Sizzle.getText = function(elem) {
      var node,
          ret = "",
          i = 0,
          nodeType = elem.nodeType;
      if (!nodeType) {
        while ((node = elem[i++])) {
          ret += getText(node);
        }
      } else if (nodeType === 1 || nodeType === 9 || nodeType === 11) {
        if (typeof elem.textContent === "string") {
          return elem.textContent;
        } else {
          for (elem = elem.firstChild; elem; elem = elem.nextSibling) {
            ret += getText(elem);
          }
        }
      } else if (nodeType === 3 || nodeType === 4) {
        return elem.nodeValue;
      }
      return ret;
    };
    Expr = Sizzle.selectors = {
      cacheLength: 50,
      createPseudo: markFunction,
      match: matchExpr,
      attrHandle: {},
      find: {},
      relative: {
        ">": {
          dir: "parentNode",
          first: true
        },
        " ": {dir: "parentNode"},
        "+": {
          dir: "previousSibling",
          first: true
        },
        "~": {dir: "previousSibling"}
      },
      preFilter: {
        "ATTR": function(match) {
          match[1] = match[1].replace(runescape, funescape);
          match[3] = (match[3] || match[4] || match[5] || "").replace(runescape, funescape);
          if (match[2] === "~=") {
            match[3] = " " + match[3] + " ";
          }
          return match.slice(0, 4);
        },
        "CHILD": function(match) {
          match[1] = match[1].toLowerCase();
          if (match[1].slice(0, 3) === "nth") {
            if (!match[3]) {
              Sizzle.error(match[0]);
            }
            match[4] = +(match[4] ? match[5] + (match[6] || 1) : 2 * (match[3] === "even" || match[3] === "odd"));
            match[5] = +((match[7] + match[8]) || match[3] === "odd");
          } else if (match[3]) {
            Sizzle.error(match[0]);
          }
          return match;
        },
        "PSEUDO": function(match) {
          var excess,
              unquoted = !match[6] && match[2];
          if (matchExpr["CHILD"].test(match[0])) {
            return null;
          }
          if (match[3]) {
            match[2] = match[4] || match[5] || "";
          } else if (unquoted && rpseudo.test(unquoted) && (excess = tokenize(unquoted, true)) && (excess = unquoted.indexOf(")", unquoted.length - excess) - unquoted.length)) {
            match[0] = match[0].slice(0, excess);
            match[2] = unquoted.slice(0, excess);
          }
          return match.slice(0, 3);
        }
      },
      filter: {
        "TAG": function(nodeNameSelector) {
          var nodeName = nodeNameSelector.replace(runescape, funescape).toLowerCase();
          return nodeNameSelector === "*" ? function() {
            return true;
          } : function(elem) {
            return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
          };
        },
        "CLASS": function(className) {
          var pattern = classCache[className + " "];
          return pattern || (pattern = new RegExp("(^|" + whitespace + ")" + className + "(" + whitespace + "|$)")) && classCache(className, function(elem) {
            return pattern.test(typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "");
          });
        },
        "ATTR": function(name, operator, check) {
          return function(elem) {
            var result = Sizzle.attr(elem, name);
            if (result == null) {
              return operator === "!=";
            }
            if (!operator) {
              return true;
            }
            result += "";
            return operator === "=" ? result === check : operator === "!=" ? result !== check : operator === "^=" ? check && result.indexOf(check) === 0 : operator === "*=" ? check && result.indexOf(check) > -1 : operator === "$=" ? check && result.slice(-check.length) === check : operator === "~=" ? (" " + result.replace(rwhitespace, " ") + " ").indexOf(check) > -1 : operator === "|=" ? result === check || result.slice(0, check.length + 1) === check + "-" : false;
          };
        },
        "CHILD": function(type, what, argument, first, last) {
          var simple = type.slice(0, 3) !== "nth",
              forward = type.slice(-4) !== "last",
              ofType = what === "of-type";
          return first === 1 && last === 0 ? function(elem) {
            return !!elem.parentNode;
          } : function(elem, context, xml) {
            var cache,
                outerCache,
                node,
                diff,
                nodeIndex,
                start,
                dir = simple !== forward ? "nextSibling" : "previousSibling",
                parent = elem.parentNode,
                name = ofType && elem.nodeName.toLowerCase(),
                useCache = !xml && !ofType;
            if (parent) {
              if (simple) {
                while (dir) {
                  node = elem;
                  while ((node = node[dir])) {
                    if (ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1) {
                      return false;
                    }
                  }
                  start = dir = type === "only" && !start && "nextSibling";
                }
                return true;
              }
              start = [forward ? parent.firstChild : parent.lastChild];
              if (forward && useCache) {
                outerCache = parent[expando] || (parent[expando] = {});
                cache = outerCache[type] || [];
                nodeIndex = cache[0] === dirruns && cache[1];
                diff = cache[0] === dirruns && cache[2];
                node = nodeIndex && parent.childNodes[nodeIndex];
                while ((node = ++nodeIndex && node && node[dir] || (diff = nodeIndex = 0) || start.pop())) {
                  if (node.nodeType === 1 && ++diff && node === elem) {
                    outerCache[type] = [dirruns, nodeIndex, diff];
                    break;
                  }
                }
              } else if (useCache && (cache = (elem[expando] || (elem[expando] = {}))[type]) && cache[0] === dirruns) {
                diff = cache[1];
              } else {
                while ((node = ++nodeIndex && node && node[dir] || (diff = nodeIndex = 0) || start.pop())) {
                  if ((ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1) && ++diff) {
                    if (useCache) {
                      (node[expando] || (node[expando] = {}))[type] = [dirruns, diff];
                    }
                    if (node === elem) {
                      break;
                    }
                  }
                }
              }
              diff -= last;
              return diff === first || (diff % first === 0 && diff / first >= 0);
            }
          };
        },
        "PSEUDO": function(pseudo, argument) {
          var args,
              fn = Expr.pseudos[pseudo] || Expr.setFilters[pseudo.toLowerCase()] || Sizzle.error("unsupported pseudo: " + pseudo);
          if (fn[expando]) {
            return fn(argument);
          }
          if (fn.length > 1) {
            args = [pseudo, pseudo, "", argument];
            return Expr.setFilters.hasOwnProperty(pseudo.toLowerCase()) ? markFunction(function(seed, matches) {
              var idx,
                  matched = fn(seed, argument),
                  i = matched.length;
              while (i--) {
                idx = indexOf(seed, matched[i]);
                seed[idx] = !(matches[idx] = matched[i]);
              }
            }) : function(elem) {
              return fn(elem, 0, args);
            };
          }
          return fn;
        }
      },
      pseudos: {
        "not": markFunction(function(selector) {
          var input = [],
              results = [],
              matcher = compile(selector.replace(rtrim, "$1"));
          return matcher[expando] ? markFunction(function(seed, matches, context, xml) {
            var elem,
                unmatched = matcher(seed, null, xml, []),
                i = seed.length;
            while (i--) {
              if ((elem = unmatched[i])) {
                seed[i] = !(matches[i] = elem);
              }
            }
          }) : function(elem, context, xml) {
            input[0] = elem;
            matcher(input, null, xml, results);
            input[0] = null;
            return !results.pop();
          };
        }),
        "has": markFunction(function(selector) {
          return function(elem) {
            return Sizzle(selector, elem).length > 0;
          };
        }),
        "contains": markFunction(function(text) {
          text = text.replace(runescape, funescape);
          return function(elem) {
            return (elem.textContent || elem.innerText || getText(elem)).indexOf(text) > -1;
          };
        }),
        "lang": markFunction(function(lang) {
          if (!ridentifier.test(lang || "")) {
            Sizzle.error("unsupported lang: " + lang);
          }
          lang = lang.replace(runescape, funescape).toLowerCase();
          return function(elem) {
            var elemLang;
            do {
              if ((elemLang = documentIsHTML ? elem.lang : elem.getAttribute("xml:lang") || elem.getAttribute("lang"))) {
                elemLang = elemLang.toLowerCase();
                return elemLang === lang || elemLang.indexOf(lang + "-") === 0;
              }
            } while ((elem = elem.parentNode) && elem.nodeType === 1);
            return false;
          };
        }),
        "target": function(elem) {
          var hash = window.location && window.location.hash;
          return hash && hash.slice(1) === elem.id;
        },
        "root": function(elem) {
          return elem === docElem;
        },
        "focus": function(elem) {
          return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
        },
        "enabled": function(elem) {
          return elem.disabled === false;
        },
        "disabled": function(elem) {
          return elem.disabled === true;
        },
        "checked": function(elem) {
          var nodeName = elem.nodeName.toLowerCase();
          return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
        },
        "selected": function(elem) {
          if (elem.parentNode) {
            elem.parentNode.selectedIndex;
          }
          return elem.selected === true;
        },
        "empty": function(elem) {
          for (elem = elem.firstChild; elem; elem = elem.nextSibling) {
            if (elem.nodeType < 6) {
              return false;
            }
          }
          return true;
        },
        "parent": function(elem) {
          return !Expr.pseudos["empty"](elem);
        },
        "header": function(elem) {
          return rheader.test(elem.nodeName);
        },
        "input": function(elem) {
          return rinputs.test(elem.nodeName);
        },
        "button": function(elem) {
          var name = elem.nodeName.toLowerCase();
          return name === "input" && elem.type === "button" || name === "button";
        },
        "text": function(elem) {
          var attr;
          return elem.nodeName.toLowerCase() === "input" && elem.type === "text" && ((attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text");
        },
        "first": createPositionalPseudo(function() {
          return [0];
        }),
        "last": createPositionalPseudo(function(matchIndexes, length) {
          return [length - 1];
        }),
        "eq": createPositionalPseudo(function(matchIndexes, length, argument) {
          return [argument < 0 ? argument + length : argument];
        }),
        "even": createPositionalPseudo(function(matchIndexes, length) {
          var i = 0;
          for (; i < length; i += 2) {
            matchIndexes.push(i);
          }
          return matchIndexes;
        }),
        "odd": createPositionalPseudo(function(matchIndexes, length) {
          var i = 1;
          for (; i < length; i += 2) {
            matchIndexes.push(i);
          }
          return matchIndexes;
        }),
        "lt": createPositionalPseudo(function(matchIndexes, length, argument) {
          var i = argument < 0 ? argument + length : argument;
          for (; --i >= 0; ) {
            matchIndexes.push(i);
          }
          return matchIndexes;
        }),
        "gt": createPositionalPseudo(function(matchIndexes, length, argument) {
          var i = argument < 0 ? argument + length : argument;
          for (; ++i < length; ) {
            matchIndexes.push(i);
          }
          return matchIndexes;
        })
      }
    };
    Expr.pseudos["nth"] = Expr.pseudos["eq"];
    for (i in {
      radio: true,
      checkbox: true,
      file: true,
      password: true,
      image: true
    }) {
      Expr.pseudos[i] = createInputPseudo(i);
    }
    for (i in {
      submit: true,
      reset: true
    }) {
      Expr.pseudos[i] = createButtonPseudo(i);
    }
    function setFilters() {}
    setFilters.prototype = Expr.filters = Expr.pseudos;
    Expr.setFilters = new setFilters();
    tokenize = Sizzle.tokenize = function(selector, parseOnly) {
      var matched,
          match,
          tokens,
          type,
          soFar,
          groups,
          preFilters,
          cached = tokenCache[selector + " "];
      if (cached) {
        return parseOnly ? 0 : cached.slice(0);
      }
      soFar = selector;
      groups = [];
      preFilters = Expr.preFilter;
      while (soFar) {
        if (!matched || (match = rcomma.exec(soFar))) {
          if (match) {
            soFar = soFar.slice(match[0].length) || soFar;
          }
          groups.push((tokens = []));
        }
        matched = false;
        if ((match = rcombinators.exec(soFar))) {
          matched = match.shift();
          tokens.push({
            value: matched,
            type: match[0].replace(rtrim, " ")
          });
          soFar = soFar.slice(matched.length);
        }
        for (type in Expr.filter) {
          if ((match = matchExpr[type].exec(soFar)) && (!preFilters[type] || (match = preFilters[type](match)))) {
            matched = match.shift();
            tokens.push({
              value: matched,
              type: type,
              matches: match
            });
            soFar = soFar.slice(matched.length);
          }
        }
        if (!matched) {
          break;
        }
      }
      return parseOnly ? soFar.length : soFar ? Sizzle.error(selector) : tokenCache(selector, groups).slice(0);
    };
    function toSelector(tokens) {
      var i = 0,
          len = tokens.length,
          selector = "";
      for (; i < len; i++) {
        selector += tokens[i].value;
      }
      return selector;
    }
    function addCombinator(matcher, combinator, base) {
      var dir = combinator.dir,
          checkNonElements = base && dir === "parentNode",
          doneName = done++;
      return combinator.first ? function(elem, context, xml) {
        while ((elem = elem[dir])) {
          if (elem.nodeType === 1 || checkNonElements) {
            return matcher(elem, context, xml);
          }
        }
      } : function(elem, context, xml) {
        var oldCache,
            outerCache,
            newCache = [dirruns, doneName];
        if (xml) {
          while ((elem = elem[dir])) {
            if (elem.nodeType === 1 || checkNonElements) {
              if (matcher(elem, context, xml)) {
                return true;
              }
            }
          }
        } else {
          while ((elem = elem[dir])) {
            if (elem.nodeType === 1 || checkNonElements) {
              outerCache = elem[expando] || (elem[expando] = {});
              if ((oldCache = outerCache[dir]) && oldCache[0] === dirruns && oldCache[1] === doneName) {
                return (newCache[2] = oldCache[2]);
              } else {
                outerCache[dir] = newCache;
                if ((newCache[2] = matcher(elem, context, xml))) {
                  return true;
                }
              }
            }
          }
        }
      };
    }
    function elementMatcher(matchers) {
      return matchers.length > 1 ? function(elem, context, xml) {
        var i = matchers.length;
        while (i--) {
          if (!matchers[i](elem, context, xml)) {
            return false;
          }
        }
        return true;
      } : matchers[0];
    }
    function multipleContexts(selector, contexts, results) {
      var i = 0,
          len = contexts.length;
      for (; i < len; i++) {
        Sizzle(selector, contexts[i], results);
      }
      return results;
    }
    function condense(unmatched, map, filter, context, xml) {
      var elem,
          newUnmatched = [],
          i = 0,
          len = unmatched.length,
          mapped = map != null;
      for (; i < len; i++) {
        if ((elem = unmatched[i])) {
          if (!filter || filter(elem, context, xml)) {
            newUnmatched.push(elem);
            if (mapped) {
              map.push(i);
            }
          }
        }
      }
      return newUnmatched;
    }
    function setMatcher(preFilter, selector, matcher, postFilter, postFinder, postSelector) {
      if (postFilter && !postFilter[expando]) {
        postFilter = setMatcher(postFilter);
      }
      if (postFinder && !postFinder[expando]) {
        postFinder = setMatcher(postFinder, postSelector);
      }
      return markFunction(function(seed, results, context, xml) {
        var temp,
            i,
            elem,
            preMap = [],
            postMap = [],
            preexisting = results.length,
            elems = seed || multipleContexts(selector || "*", context.nodeType ? [context] : context, []),
            matcherIn = preFilter && (seed || !selector) ? condense(elems, preMap, preFilter, context, xml) : elems,
            matcherOut = matcher ? postFinder || (seed ? preFilter : preexisting || postFilter) ? [] : results : matcherIn;
        if (matcher) {
          matcher(matcherIn, matcherOut, context, xml);
        }
        if (postFilter) {
          temp = condense(matcherOut, postMap);
          postFilter(temp, [], context, xml);
          i = temp.length;
          while (i--) {
            if ((elem = temp[i])) {
              matcherOut[postMap[i]] = !(matcherIn[postMap[i]] = elem);
            }
          }
        }
        if (seed) {
          if (postFinder || preFilter) {
            if (postFinder) {
              temp = [];
              i = matcherOut.length;
              while (i--) {
                if ((elem = matcherOut[i])) {
                  temp.push((matcherIn[i] = elem));
                }
              }
              postFinder(null, (matcherOut = []), temp, xml);
            }
            i = matcherOut.length;
            while (i--) {
              if ((elem = matcherOut[i]) && (temp = postFinder ? indexOf(seed, elem) : preMap[i]) > -1) {
                seed[temp] = !(results[temp] = elem);
              }
            }
          }
        } else {
          matcherOut = condense(matcherOut === results ? matcherOut.splice(preexisting, matcherOut.length) : matcherOut);
          if (postFinder) {
            postFinder(null, results, matcherOut, xml);
          } else {
            push.apply(results, matcherOut);
          }
        }
      });
    }
    function matcherFromTokens(tokens) {
      var checkContext,
          matcher,
          j,
          len = tokens.length,
          leadingRelative = Expr.relative[tokens[0].type],
          implicitRelative = leadingRelative || Expr.relative[" "],
          i = leadingRelative ? 1 : 0,
          matchContext = addCombinator(function(elem) {
            return elem === checkContext;
          }, implicitRelative, true),
          matchAnyContext = addCombinator(function(elem) {
            return indexOf(checkContext, elem) > -1;
          }, implicitRelative, true),
          matchers = [function(elem, context, xml) {
            var ret = (!leadingRelative && (xml || context !== outermostContext)) || ((checkContext = context).nodeType ? matchContext(elem, context, xml) : matchAnyContext(elem, context, xml));
            checkContext = null;
            return ret;
          }];
      for (; i < len; i++) {
        if ((matcher = Expr.relative[tokens[i].type])) {
          matchers = [addCombinator(elementMatcher(matchers), matcher)];
        } else {
          matcher = Expr.filter[tokens[i].type].apply(null, tokens[i].matches);
          if (matcher[expando]) {
            j = ++i;
            for (; j < len; j++) {
              if (Expr.relative[tokens[j].type]) {
                break;
              }
            }
            return setMatcher(i > 1 && elementMatcher(matchers), i > 1 && toSelector(tokens.slice(0, i - 1).concat({value: tokens[i - 2].type === " " ? "*" : ""})).replace(rtrim, "$1"), matcher, i < j && matcherFromTokens(tokens.slice(i, j)), j < len && matcherFromTokens((tokens = tokens.slice(j))), j < len && toSelector(tokens));
          }
          matchers.push(matcher);
        }
      }
      return elementMatcher(matchers);
    }
    function matcherFromGroupMatchers(elementMatchers, setMatchers) {
      var bySet = setMatchers.length > 0,
          byElement = elementMatchers.length > 0,
          superMatcher = function(seed, context, xml, results, outermost) {
            var elem,
                j,
                matcher,
                matchedCount = 0,
                i = "0",
                unmatched = seed && [],
                setMatched = [],
                contextBackup = outermostContext,
                elems = seed || byElement && Expr.find["TAG"]("*", outermost),
                dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
                len = elems.length;
            if (outermost) {
              outermostContext = context !== document && context;
            }
            for (; i !== len && (elem = elems[i]) != null; i++) {
              if (byElement && elem) {
                j = 0;
                while ((matcher = elementMatchers[j++])) {
                  if (matcher(elem, context, xml)) {
                    results.push(elem);
                    break;
                  }
                }
                if (outermost) {
                  dirruns = dirrunsUnique;
                }
              }
              if (bySet) {
                if ((elem = !matcher && elem)) {
                  matchedCount--;
                }
                if (seed) {
                  unmatched.push(elem);
                }
              }
            }
            matchedCount += i;
            if (bySet && i !== matchedCount) {
              j = 0;
              while ((matcher = setMatchers[j++])) {
                matcher(unmatched, setMatched, context, xml);
              }
              if (seed) {
                if (matchedCount > 0) {
                  while (i--) {
                    if (!(unmatched[i] || setMatched[i])) {
                      setMatched[i] = pop.call(results);
                    }
                  }
                }
                setMatched = condense(setMatched);
              }
              push.apply(results, setMatched);
              if (outermost && !seed && setMatched.length > 0 && (matchedCount + setMatchers.length) > 1) {
                Sizzle.uniqueSort(results);
              }
            }
            if (outermost) {
              dirruns = dirrunsUnique;
              outermostContext = contextBackup;
            }
            return unmatched;
          };
      return bySet ? markFunction(superMatcher) : superMatcher;
    }
    compile = Sizzle.compile = function(selector, match) {
      var i,
          setMatchers = [],
          elementMatchers = [],
          cached = compilerCache[selector + " "];
      if (!cached) {
        if (!match) {
          match = tokenize(selector);
        }
        i = match.length;
        while (i--) {
          cached = matcherFromTokens(match[i]);
          if (cached[expando]) {
            setMatchers.push(cached);
          } else {
            elementMatchers.push(cached);
          }
        }
        cached = compilerCache(selector, matcherFromGroupMatchers(elementMatchers, setMatchers));
        cached.selector = selector;
      }
      return cached;
    };
    select = Sizzle.select = function(selector, context, results, seed) {
      var i,
          tokens,
          token,
          type,
          find,
          compiled = typeof selector === "function" && selector,
          match = !seed && tokenize((selector = compiled.selector || selector));
      results = results || [];
      if (match.length === 1) {
        tokens = match[0] = match[0].slice(0);
        if (tokens.length > 2 && (token = tokens[0]).type === "ID" && support.getById && context.nodeType === 9 && documentIsHTML && Expr.relative[tokens[1].type]) {
          context = (Expr.find["ID"](token.matches[0].replace(runescape, funescape), context) || [])[0];
          if (!context) {
            return results;
          } else if (compiled) {
            context = context.parentNode;
          }
          selector = selector.slice(tokens.shift().value.length);
        }
        i = matchExpr["needsContext"].test(selector) ? 0 : tokens.length;
        while (i--) {
          token = tokens[i];
          if (Expr.relative[(type = token.type)]) {
            break;
          }
          if ((find = Expr.find[type])) {
            if ((seed = find(token.matches[0].replace(runescape, funescape), rsibling.test(tokens[0].type) && testContext(context.parentNode) || context))) {
              tokens.splice(i, 1);
              selector = seed.length && toSelector(tokens);
              if (!selector) {
                push.apply(results, seed);
                return results;
              }
              break;
            }
          }
        }
      }
      (compiled || compile(selector, match))(seed, context, !documentIsHTML, results, rsibling.test(selector) && testContext(context.parentNode) || context);
      return results;
    };
    support.sortStable = expando.split("").sort(sortOrder).join("") === expando;
    support.detectDuplicates = !!hasDuplicate;
    setDocument();
    support.sortDetached = assert(function(div1) {
      return div1.compareDocumentPosition(document.createElement("div")) & 1;
    });
    if (!assert(function(div) {
      div.innerHTML = "<a href='#'></a>";
      return div.firstChild.getAttribute("href") === "#";
    })) {
      addHandle("type|href|height|width", function(elem, name, isXML) {
        if (!isXML) {
          return elem.getAttribute(name, name.toLowerCase() === "type" ? 1 : 2);
        }
      });
    }
    if (!support.attributes || !assert(function(div) {
      div.innerHTML = "<input/>";
      div.firstChild.setAttribute("value", "");
      return div.firstChild.getAttribute("value") === "";
    })) {
      addHandle("value", function(elem, name, isXML) {
        if (!isXML && elem.nodeName.toLowerCase() === "input") {
          return elem.defaultValue;
        }
      });
    }
    if (!assert(function(div) {
      return div.getAttribute("disabled") == null;
    })) {
      addHandle(booleans, function(elem, name, isXML) {
        var val;
        if (!isXML) {
          return elem[name] === true ? name.toLowerCase() : (val = elem.getAttributeNode(name)) && val.specified ? val.value : null;
        }
      });
    }
    return Sizzle;
  })(window);
  jQuery.find = Sizzle;
  jQuery.expr = Sizzle.selectors;
  jQuery.expr[":"] = jQuery.expr.pseudos;
  jQuery.unique = Sizzle.uniqueSort;
  jQuery.text = Sizzle.getText;
  jQuery.isXMLDoc = Sizzle.isXML;
  jQuery.contains = Sizzle.contains;
  var rneedsContext = jQuery.expr.match.needsContext;
  var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/);
  var risSimple = /^.[^:#\[\.,]*$/;
  function winnow(elements, qualifier, not) {
    if (jQuery.isFunction(qualifier)) {
      return jQuery.grep(elements, function(elem, i) {
        return !!qualifier.call(elem, i, elem) !== not;
      });
    }
    if (qualifier.nodeType) {
      return jQuery.grep(elements, function(elem) {
        return (elem === qualifier) !== not;
      });
    }
    if (typeof qualifier === "string") {
      if (risSimple.test(qualifier)) {
        return jQuery.filter(qualifier, elements, not);
      }
      qualifier = jQuery.filter(qualifier, elements);
    }
    return jQuery.grep(elements, function(elem) {
      return (indexOf.call(qualifier, elem) >= 0) !== not;
    });
  }
  jQuery.filter = function(expr, elems, not) {
    var elem = elems[0];
    if (not) {
      expr = ":not(" + expr + ")";
    }
    return elems.length === 1 && elem.nodeType === 1 ? jQuery.find.matchesSelector(elem, expr) ? [elem] : [] : jQuery.find.matches(expr, jQuery.grep(elems, function(elem) {
      return elem.nodeType === 1;
    }));
  };
  jQuery.fn.extend({
    find: function(selector) {
      var i,
          len = this.length,
          ret = [],
          self = this;
      if (typeof selector !== "string") {
        return this.pushStack(jQuery(selector).filter(function() {
          for (i = 0; i < len; i++) {
            if (jQuery.contains(self[i], this)) {
              return true;
            }
          }
        }));
      }
      for (i = 0; i < len; i++) {
        jQuery.find(selector, self[i], ret);
      }
      ret = this.pushStack(len > 1 ? jQuery.unique(ret) : ret);
      ret.selector = this.selector ? this.selector + " " + selector : selector;
      return ret;
    },
    filter: function(selector) {
      return this.pushStack(winnow(this, selector || [], false));
    },
    not: function(selector) {
      return this.pushStack(winnow(this, selector || [], true));
    },
    is: function(selector) {
      return !!winnow(this, typeof selector === "string" && rneedsContext.test(selector) ? jQuery(selector) : selector || [], false).length;
    }
  });
  var rootjQuery,
      rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,
      init = jQuery.fn.init = function(selector, context) {
        var match,
            elem;
        if (!selector) {
          return this;
        }
        if (typeof selector === "string") {
          if (selector[0] === "<" && selector[selector.length - 1] === ">" && selector.length >= 3) {
            match = [null, selector, null];
          } else {
            match = rquickExpr.exec(selector);
          }
          if (match && (match[1] || !context)) {
            if (match[1]) {
              context = context instanceof jQuery ? context[0] : context;
              jQuery.merge(this, jQuery.parseHTML(match[1], context && context.nodeType ? context.ownerDocument || context : document, true));
              if (rsingleTag.test(match[1]) && jQuery.isPlainObject(context)) {
                for (match in context) {
                  if (jQuery.isFunction(this[match])) {
                    this[match](context[match]);
                  } else {
                    this.attr(match, context[match]);
                  }
                }
              }
              return this;
            } else {
              elem = document.getElementById(match[2]);
              if (elem && elem.parentNode) {
                this.length = 1;
                this[0] = elem;
              }
              this.context = document;
              this.selector = selector;
              return this;
            }
          } else if (!context || context.jquery) {
            return (context || rootjQuery).find(selector);
          } else {
            return this.constructor(context).find(selector);
          }
        } else if (selector.nodeType) {
          this.context = this[0] = selector;
          this.length = 1;
          return this;
        } else if (jQuery.isFunction(selector)) {
          return typeof rootjQuery.ready !== "undefined" ? rootjQuery.ready(selector) : selector(jQuery);
        }
        if (selector.selector !== undefined) {
          this.selector = selector.selector;
          this.context = selector.context;
        }
        return jQuery.makeArray(selector, this);
      };
  init.prototype = jQuery.fn;
  rootjQuery = jQuery(document);
  var rparentsprev = /^(?:parents|prev(?:Until|All))/,
      guaranteedUnique = {
        children: true,
        contents: true,
        next: true,
        prev: true
      };
  jQuery.extend({
    dir: function(elem, dir, until) {
      var matched = [],
          truncate = until !== undefined;
      while ((elem = elem[dir]) && elem.nodeType !== 9) {
        if (elem.nodeType === 1) {
          if (truncate && jQuery(elem).is(until)) {
            break;
          }
          matched.push(elem);
        }
      }
      return matched;
    },
    sibling: function(n, elem) {
      var matched = [];
      for (; n; n = n.nextSibling) {
        if (n.nodeType === 1 && n !== elem) {
          matched.push(n);
        }
      }
      return matched;
    }
  });
  jQuery.fn.extend({
    has: function(target) {
      var targets = jQuery(target, this),
          l = targets.length;
      return this.filter(function() {
        var i = 0;
        for (; i < l; i++) {
          if (jQuery.contains(this, targets[i])) {
            return true;
          }
        }
      });
    },
    closest: function(selectors, context) {
      var cur,
          i = 0,
          l = this.length,
          matched = [],
          pos = rneedsContext.test(selectors) || typeof selectors !== "string" ? jQuery(selectors, context || this.context) : 0;
      for (; i < l; i++) {
        for (cur = this[i]; cur && cur !== context; cur = cur.parentNode) {
          if (cur.nodeType < 11 && (pos ? pos.index(cur) > -1 : cur.nodeType === 1 && jQuery.find.matchesSelector(cur, selectors))) {
            matched.push(cur);
            break;
          }
        }
      }
      return this.pushStack(matched.length > 1 ? jQuery.unique(matched) : matched);
    },
    index: function(elem) {
      if (!elem) {
        return (this[0] && this[0].parentNode) ? this.first().prevAll().length : -1;
      }
      if (typeof elem === "string") {
        return indexOf.call(jQuery(elem), this[0]);
      }
      return indexOf.call(this, elem.jquery ? elem[0] : elem);
    },
    add: function(selector, context) {
      return this.pushStack(jQuery.unique(jQuery.merge(this.get(), jQuery(selector, context))));
    },
    addBack: function(selector) {
      return this.add(selector == null ? this.prevObject : this.prevObject.filter(selector));
    }
  });
  function sibling(cur, dir) {
    while ((cur = cur[dir]) && cur.nodeType !== 1) {}
    return cur;
  }
  jQuery.each({
    parent: function(elem) {
      var parent = elem.parentNode;
      return parent && parent.nodeType !== 11 ? parent : null;
    },
    parents: function(elem) {
      return jQuery.dir(elem, "parentNode");
    },
    parentsUntil: function(elem, i, until) {
      return jQuery.dir(elem, "parentNode", until);
    },
    next: function(elem) {
      return sibling(elem, "nextSibling");
    },
    prev: function(elem) {
      return sibling(elem, "previousSibling");
    },
    nextAll: function(elem) {
      return jQuery.dir(elem, "nextSibling");
    },
    prevAll: function(elem) {
      return jQuery.dir(elem, "previousSibling");
    },
    nextUntil: function(elem, i, until) {
      return jQuery.dir(elem, "nextSibling", until);
    },
    prevUntil: function(elem, i, until) {
      return jQuery.dir(elem, "previousSibling", until);
    },
    siblings: function(elem) {
      return jQuery.sibling((elem.parentNode || {}).firstChild, elem);
    },
    children: function(elem) {
      return jQuery.sibling(elem.firstChild);
    },
    contents: function(elem) {
      return elem.contentDocument || jQuery.merge([], elem.childNodes);
    }
  }, function(name, fn) {
    jQuery.fn[name] = function(until, selector) {
      var matched = jQuery.map(this, fn, until);
      if (name.slice(-5) !== "Until") {
        selector = until;
      }
      if (selector && typeof selector === "string") {
        matched = jQuery.filter(selector, matched);
      }
      if (this.length > 1) {
        if (!guaranteedUnique[name]) {
          jQuery.unique(matched);
        }
        if (rparentsprev.test(name)) {
          matched.reverse();
        }
      }
      return this.pushStack(matched);
    };
  });
  var rnotwhite = (/\S+/g);
  var optionsCache = {};
  function createOptions(options) {
    var object = optionsCache[options] = {};
    jQuery.each(options.match(rnotwhite) || [], function(_, flag) {
      object[flag] = true;
    });
    return object;
  }
  jQuery.Callbacks = function(options) {
    options = typeof options === "string" ? (optionsCache[options] || createOptions(options)) : jQuery.extend({}, options);
    var memory,
        fired,
        firing,
        firingStart,
        firingLength,
        firingIndex,
        list = [],
        stack = !options.once && [],
        fire = function(data) {
          memory = options.memory && data;
          fired = true;
          firingIndex = firingStart || 0;
          firingStart = 0;
          firingLength = list.length;
          firing = true;
          for (; list && firingIndex < firingLength; firingIndex++) {
            if (list[firingIndex].apply(data[0], data[1]) === false && options.stopOnFalse) {
              memory = false;
              break;
            }
          }
          firing = false;
          if (list) {
            if (stack) {
              if (stack.length) {
                fire(stack.shift());
              }
            } else if (memory) {
              list = [];
            } else {
              self.disable();
            }
          }
        },
        self = {
          add: function() {
            if (list) {
              var start = list.length;
              (function add(args) {
                jQuery.each(args, function(_, arg) {
                  var type = jQuery.type(arg);
                  if (type === "function") {
                    if (!options.unique || !self.has(arg)) {
                      list.push(arg);
                    }
                  } else if (arg && arg.length && type !== "string") {
                    add(arg);
                  }
                });
              })(arguments);
              if (firing) {
                firingLength = list.length;
              } else if (memory) {
                firingStart = start;
                fire(memory);
              }
            }
            return this;
          },
          remove: function() {
            if (list) {
              jQuery.each(arguments, function(_, arg) {
                var index;
                while ((index = jQuery.inArray(arg, list, index)) > -1) {
                  list.splice(index, 1);
                  if (firing) {
                    if (index <= firingLength) {
                      firingLength--;
                    }
                    if (index <= firingIndex) {
                      firingIndex--;
                    }
                  }
                }
              });
            }
            return this;
          },
          has: function(fn) {
            return fn ? jQuery.inArray(fn, list) > -1 : !!(list && list.length);
          },
          empty: function() {
            list = [];
            firingLength = 0;
            return this;
          },
          disable: function() {
            list = stack = memory = undefined;
            return this;
          },
          disabled: function() {
            return !list;
          },
          lock: function() {
            stack = undefined;
            if (!memory) {
              self.disable();
            }
            return this;
          },
          locked: function() {
            return !stack;
          },
          fireWith: function(context, args) {
            if (list && (!fired || stack)) {
              args = args || [];
              args = [context, args.slice ? args.slice() : args];
              if (firing) {
                stack.push(args);
              } else {
                fire(args);
              }
            }
            return this;
          },
          fire: function() {
            self.fireWith(this, arguments);
            return this;
          },
          fired: function() {
            return !!fired;
          }
        };
    return self;
  };
  jQuery.extend({
    Deferred: function(func) {
      var tuples = [["resolve", "done", jQuery.Callbacks("once memory"), "resolved"], ["reject", "fail", jQuery.Callbacks("once memory"), "rejected"], ["notify", "progress", jQuery.Callbacks("memory")]],
          state = "pending",
          promise = {
            state: function() {
              return state;
            },
            always: function() {
              deferred.done(arguments).fail(arguments);
              return this;
            },
            then: function() {
              var fns = arguments;
              return jQuery.Deferred(function(newDefer) {
                jQuery.each(tuples, function(i, tuple) {
                  var fn = jQuery.isFunction(fns[i]) && fns[i];
                  deferred[tuple[1]](function() {
                    var returned = fn && fn.apply(this, arguments);
                    if (returned && jQuery.isFunction(returned.promise)) {
                      returned.promise().done(newDefer.resolve).fail(newDefer.reject).progress(newDefer.notify);
                    } else {
                      newDefer[tuple[0] + "With"](this === promise ? newDefer.promise() : this, fn ? [returned] : arguments);
                    }
                  });
                });
                fns = null;
              }).promise();
            },
            promise: function(obj) {
              return obj != null ? jQuery.extend(obj, promise) : promise;
            }
          },
          deferred = {};
      promise.pipe = promise.then;
      jQuery.each(tuples, function(i, tuple) {
        var list = tuple[2],
            stateString = tuple[3];
        promise[tuple[1]] = list.add;
        if (stateString) {
          list.add(function() {
            state = stateString;
          }, tuples[i ^ 1][2].disable, tuples[2][2].lock);
        }
        deferred[tuple[0]] = function() {
          deferred[tuple[0] + "With"](this === deferred ? promise : this, arguments);
          return this;
        };
        deferred[tuple[0] + "With"] = list.fireWith;
      });
      promise.promise(deferred);
      if (func) {
        func.call(deferred, deferred);
      }
      return deferred;
    },
    when: function(subordinate) {
      var i = 0,
          resolveValues = slice.call(arguments),
          length = resolveValues.length,
          remaining = length !== 1 || (subordinate && jQuery.isFunction(subordinate.promise)) ? length : 0,
          deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
          updateFunc = function(i, contexts, values) {
            return function(value) {
              contexts[i] = this;
              values[i] = arguments.length > 1 ? slice.call(arguments) : value;
              if (values === progressValues) {
                deferred.notifyWith(contexts, values);
              } else if (!(--remaining)) {
                deferred.resolveWith(contexts, values);
              }
            };
          },
          progressValues,
          progressContexts,
          resolveContexts;
      if (length > 1) {
        progressValues = new Array(length);
        progressContexts = new Array(length);
        resolveContexts = new Array(length);
        for (; i < length; i++) {
          if (resolveValues[i] && jQuery.isFunction(resolveValues[i].promise)) {
            resolveValues[i].promise().done(updateFunc(i, resolveContexts, resolveValues)).fail(deferred.reject).progress(updateFunc(i, progressContexts, progressValues));
          } else {
            --remaining;
          }
        }
      }
      if (!remaining) {
        deferred.resolveWith(resolveContexts, resolveValues);
      }
      return deferred.promise();
    }
  });
  var readyList;
  jQuery.fn.ready = function(fn) {
    jQuery.ready.promise().done(fn);
    return this;
  };
  jQuery.extend({
    isReady: false,
    readyWait: 1,
    holdReady: function(hold) {
      if (hold) {
        jQuery.readyWait++;
      } else {
        jQuery.ready(true);
      }
    },
    ready: function(wait) {
      if (wait === true ? --jQuery.readyWait : jQuery.isReady) {
        return;
      }
      jQuery.isReady = true;
      if (wait !== true && --jQuery.readyWait > 0) {
        return;
      }
      readyList.resolveWith(document, [jQuery]);
      if (jQuery.fn.triggerHandler) {
        jQuery(document).triggerHandler("ready");
        jQuery(document).off("ready");
      }
    }
  });
  function completed() {
    document.removeEventListener("DOMContentLoaded", completed, false);
    window.removeEventListener("load", completed, false);
    jQuery.ready();
  }
  jQuery.ready.promise = function(obj) {
    if (!readyList) {
      readyList = jQuery.Deferred();
      if (document.readyState === "complete") {
        setTimeout(jQuery.ready);
      } else {
        document.addEventListener("DOMContentLoaded", completed, false);
        window.addEventListener("load", completed, false);
      }
    }
    return readyList.promise(obj);
  };
  jQuery.ready.promise();
  var access = jQuery.access = function(elems, fn, key, value, chainable, emptyGet, raw) {
    var i = 0,
        len = elems.length,
        bulk = key == null;
    if (jQuery.type(key) === "object") {
      chainable = true;
      for (i in key) {
        jQuery.access(elems, fn, i, key[i], true, emptyGet, raw);
      }
    } else if (value !== undefined) {
      chainable = true;
      if (!jQuery.isFunction(value)) {
        raw = true;
      }
      if (bulk) {
        if (raw) {
          fn.call(elems, value);
          fn = null;
        } else {
          bulk = fn;
          fn = function(elem, key, value) {
            return bulk.call(jQuery(elem), value);
          };
        }
      }
      if (fn) {
        for (; i < len; i++) {
          fn(elems[i], key, raw ? value : value.call(elems[i], i, fn(elems[i], key)));
        }
      }
    }
    return chainable ? elems : bulk ? fn.call(elems) : len ? fn(elems[0], key) : emptyGet;
  };
  jQuery.acceptData = function(owner) {
    return owner.nodeType === 1 || owner.nodeType === 9 || !(+owner.nodeType);
  };
  function Data() {
    Object.defineProperty(this.cache = {}, 0, {get: function() {
        return {};
      }});
    this.expando = jQuery.expando + Data.uid++;
  }
  Data.uid = 1;
  Data.accepts = jQuery.acceptData;
  Data.prototype = {
    key: function(owner) {
      if (!Data.accepts(owner)) {
        return 0;
      }
      var descriptor = {},
          unlock = owner[this.expando];
      if (!unlock) {
        unlock = Data.uid++;
        try {
          descriptor[this.expando] = {value: unlock};
          Object.defineProperties(owner, descriptor);
        } catch (e) {
          descriptor[this.expando] = unlock;
          jQuery.extend(owner, descriptor);
        }
      }
      if (!this.cache[unlock]) {
        this.cache[unlock] = {};
      }
      return unlock;
    },
    set: function(owner, data, value) {
      var prop,
          unlock = this.key(owner),
          cache = this.cache[unlock];
      if (typeof data === "string") {
        cache[data] = value;
      } else {
        if (jQuery.isEmptyObject(cache)) {
          jQuery.extend(this.cache[unlock], data);
        } else {
          for (prop in data) {
            cache[prop] = data[prop];
          }
        }
      }
      return cache;
    },
    get: function(owner, key) {
      var cache = this.cache[this.key(owner)];
      return key === undefined ? cache : cache[key];
    },
    access: function(owner, key, value) {
      var stored;
      if (key === undefined || ((key && typeof key === "string") && value === undefined)) {
        stored = this.get(owner, key);
        return stored !== undefined ? stored : this.get(owner, jQuery.camelCase(key));
      }
      this.set(owner, key, value);
      return value !== undefined ? value : key;
    },
    remove: function(owner, key) {
      var i,
          name,
          camel,
          unlock = this.key(owner),
          cache = this.cache[unlock];
      if (key === undefined) {
        this.cache[unlock] = {};
      } else {
        if (jQuery.isArray(key)) {
          name = key.concat(key.map(jQuery.camelCase));
        } else {
          camel = jQuery.camelCase(key);
          if (key in cache) {
            name = [key, camel];
          } else {
            name = camel;
            name = name in cache ? [name] : (name.match(rnotwhite) || []);
          }
        }
        i = name.length;
        while (i--) {
          delete cache[name[i]];
        }
      }
    },
    hasData: function(owner) {
      return !jQuery.isEmptyObject(this.cache[owner[this.expando]] || {});
    },
    discard: function(owner) {
      if (owner[this.expando]) {
        delete this.cache[owner[this.expando]];
      }
    }
  };
  var data_priv = new Data();
  var data_user = new Data();
  var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
      rmultiDash = /([A-Z])/g;
  function dataAttr(elem, key, data) {
    var name;
    if (data === undefined && elem.nodeType === 1) {
      name = "data-" + key.replace(rmultiDash, "-$1").toLowerCase();
      data = elem.getAttribute(name);
      if (typeof data === "string") {
        try {
          data = data === "true" ? true : data === "false" ? false : data === "null" ? null : +data + "" === data ? +data : rbrace.test(data) ? jQuery.parseJSON(data) : data;
        } catch (e) {}
        data_user.set(elem, key, data);
      } else {
        data = undefined;
      }
    }
    return data;
  }
  jQuery.extend({
    hasData: function(elem) {
      return data_user.hasData(elem) || data_priv.hasData(elem);
    },
    data: function(elem, name, data) {
      return data_user.access(elem, name, data);
    },
    removeData: function(elem, name) {
      data_user.remove(elem, name);
    },
    _data: function(elem, name, data) {
      return data_priv.access(elem, name, data);
    },
    _removeData: function(elem, name) {
      data_priv.remove(elem, name);
    }
  });
  jQuery.fn.extend({
    data: function(key, value) {
      var i,
          name,
          data,
          elem = this[0],
          attrs = elem && elem.attributes;
      if (key === undefined) {
        if (this.length) {
          data = data_user.get(elem);
          if (elem.nodeType === 1 && !data_priv.get(elem, "hasDataAttrs")) {
            i = attrs.length;
            while (i--) {
              if (attrs[i]) {
                name = attrs[i].name;
                if (name.indexOf("data-") === 0) {
                  name = jQuery.camelCase(name.slice(5));
                  dataAttr(elem, name, data[name]);
                }
              }
            }
            data_priv.set(elem, "hasDataAttrs", true);
          }
        }
        return data;
      }
      if (typeof key === "object") {
        return this.each(function() {
          data_user.set(this, key);
        });
      }
      return access(this, function(value) {
        var data,
            camelKey = jQuery.camelCase(key);
        if (elem && value === undefined) {
          data = data_user.get(elem, key);
          if (data !== undefined) {
            return data;
          }
          data = data_user.get(elem, camelKey);
          if (data !== undefined) {
            return data;
          }
          data = dataAttr(elem, camelKey, undefined);
          if (data !== undefined) {
            return data;
          }
          return;
        }
        this.each(function() {
          var data = data_user.get(this, camelKey);
          data_user.set(this, camelKey, value);
          if (key.indexOf("-") !== -1 && data !== undefined) {
            data_user.set(this, key, value);
          }
        });
      }, null, value, arguments.length > 1, null, true);
    },
    removeData: function(key) {
      return this.each(function() {
        data_user.remove(this, key);
      });
    }
  });
  jQuery.extend({
    queue: function(elem, type, data) {
      var queue;
      if (elem) {
        type = (type || "fx") + "queue";
        queue = data_priv.get(elem, type);
        if (data) {
          if (!queue || jQuery.isArray(data)) {
            queue = data_priv.access(elem, type, jQuery.makeArray(data));
          } else {
            queue.push(data);
          }
        }
        return queue || [];
      }
    },
    dequeue: function(elem, type) {
      type = type || "fx";
      var queue = jQuery.queue(elem, type),
          startLength = queue.length,
          fn = queue.shift(),
          hooks = jQuery._queueHooks(elem, type),
          next = function() {
            jQuery.dequeue(elem, type);
          };
      if (fn === "inprogress") {
        fn = queue.shift();
        startLength--;
      }
      if (fn) {
        if (type === "fx") {
          queue.unshift("inprogress");
        }
        delete hooks.stop;
        fn.call(elem, next, hooks);
      }
      if (!startLength && hooks) {
        hooks.empty.fire();
      }
    },
    _queueHooks: function(elem, type) {
      var key = type + "queueHooks";
      return data_priv.get(elem, key) || data_priv.access(elem, key, {empty: jQuery.Callbacks("once memory").add(function() {
          data_priv.remove(elem, [type + "queue", key]);
        })});
    }
  });
  jQuery.fn.extend({
    queue: function(type, data) {
      var setter = 2;
      if (typeof type !== "string") {
        data = type;
        type = "fx";
        setter--;
      }
      if (arguments.length < setter) {
        return jQuery.queue(this[0], type);
      }
      return data === undefined ? this : this.each(function() {
        var queue = jQuery.queue(this, type, data);
        jQuery._queueHooks(this, type);
        if (type === "fx" && queue[0] !== "inprogress") {
          jQuery.dequeue(this, type);
        }
      });
    },
    dequeue: function(type) {
      return this.each(function() {
        jQuery.dequeue(this, type);
      });
    },
    clearQueue: function(type) {
      return this.queue(type || "fx", []);
    },
    promise: function(type, obj) {
      var tmp,
          count = 1,
          defer = jQuery.Deferred(),
          elements = this,
          i = this.length,
          resolve = function() {
            if (!(--count)) {
              defer.resolveWith(elements, [elements]);
            }
          };
      if (typeof type !== "string") {
        obj = type;
        type = undefined;
      }
      type = type || "fx";
      while (i--) {
        tmp = data_priv.get(elements[i], type + "queueHooks");
        if (tmp && tmp.empty) {
          count++;
          tmp.empty.add(resolve);
        }
      }
      resolve();
      return defer.promise(obj);
    }
  });
  var pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source;
  var cssExpand = ["Top", "Right", "Bottom", "Left"];
  var isHidden = function(elem, el) {
    elem = el || elem;
    return jQuery.css(elem, "display") === "none" || !jQuery.contains(elem.ownerDocument, elem);
  };
  var rcheckableType = (/^(?:checkbox|radio)$/i);
  (function() {
    var fragment = document.createDocumentFragment(),
        div = fragment.appendChild(document.createElement("div")),
        input = document.createElement("input");
    input.setAttribute("type", "radio");
    input.setAttribute("checked", "checked");
    input.setAttribute("name", "t");
    div.appendChild(input);
    support.checkClone = div.cloneNode(true).cloneNode(true).lastChild.checked;
    div.innerHTML = "<textarea>x</textarea>";
    support.noCloneChecked = !!div.cloneNode(true).lastChild.defaultValue;
  })();
  var strundefined = typeof undefined;
  support.focusinBubbles = "onfocusin" in window;
  var rkeyEvent = /^key/,
      rmouseEvent = /^(?:mouse|pointer|contextmenu)|click/,
      rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
      rtypenamespace = /^([^.]*)(?:\.(.+)|)$/;
  function returnTrue() {
    return true;
  }
  function returnFalse() {
    return false;
  }
  function safeActiveElement() {
    try {
      return document.activeElement;
    } catch (err) {}
  }
  jQuery.event = {
    global: {},
    add: function(elem, types, handler, data, selector) {
      var handleObjIn,
          eventHandle,
          tmp,
          events,
          t,
          handleObj,
          special,
          handlers,
          type,
          namespaces,
          origType,
          elemData = data_priv.get(elem);
      if (!elemData) {
        return;
      }
      if (handler.handler) {
        handleObjIn = handler;
        handler = handleObjIn.handler;
        selector = handleObjIn.selector;
      }
      if (!handler.guid) {
        handler.guid = jQuery.guid++;
      }
      if (!(events = elemData.events)) {
        events = elemData.events = {};
      }
      if (!(eventHandle = elemData.handle)) {
        eventHandle = elemData.handle = function(e) {
          return typeof jQuery !== strundefined && jQuery.event.triggered !== e.type ? jQuery.event.dispatch.apply(elem, arguments) : undefined;
        };
      }
      types = (types || "").match(rnotwhite) || [""];
      t = types.length;
      while (t--) {
        tmp = rtypenamespace.exec(types[t]) || [];
        type = origType = tmp[1];
        namespaces = (tmp[2] || "").split(".").sort();
        if (!type) {
          continue;
        }
        special = jQuery.event.special[type] || {};
        type = (selector ? special.delegateType : special.bindType) || type;
        special = jQuery.event.special[type] || {};
        handleObj = jQuery.extend({
          type: type,
          origType: origType,
          data: data,
          handler: handler,
          guid: handler.guid,
          selector: selector,
          needsContext: selector && jQuery.expr.match.needsContext.test(selector),
          namespace: namespaces.join(".")
        }, handleObjIn);
        if (!(handlers = events[type])) {
          handlers = events[type] = [];
          handlers.delegateCount = 0;
          if (!special.setup || special.setup.call(elem, data, namespaces, eventHandle) === false) {
            if (elem.addEventListener) {
              elem.addEventListener(type, eventHandle, false);
            }
          }
        }
        if (special.add) {
          special.add.call(elem, handleObj);
          if (!handleObj.handler.guid) {
            handleObj.handler.guid = handler.guid;
          }
        }
        if (selector) {
          handlers.splice(handlers.delegateCount++, 0, handleObj);
        } else {
          handlers.push(handleObj);
        }
        jQuery.event.global[type] = true;
      }
    },
    remove: function(elem, types, handler, selector, mappedTypes) {
      var j,
          origCount,
          tmp,
          events,
          t,
          handleObj,
          special,
          handlers,
          type,
          namespaces,
          origType,
          elemData = data_priv.hasData(elem) && data_priv.get(elem);
      if (!elemData || !(events = elemData.events)) {
        return;
      }
      types = (types || "").match(rnotwhite) || [""];
      t = types.length;
      while (t--) {
        tmp = rtypenamespace.exec(types[t]) || [];
        type = origType = tmp[1];
        namespaces = (tmp[2] || "").split(".").sort();
        if (!type) {
          for (type in events) {
            jQuery.event.remove(elem, type + types[t], handler, selector, true);
          }
          continue;
        }
        special = jQuery.event.special[type] || {};
        type = (selector ? special.delegateType : special.bindType) || type;
        handlers = events[type] || [];
        tmp = tmp[2] && new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)");
        origCount = j = handlers.length;
        while (j--) {
          handleObj = handlers[j];
          if ((mappedTypes || origType === handleObj.origType) && (!handler || handler.guid === handleObj.guid) && (!tmp || tmp.test(handleObj.namespace)) && (!selector || selector === handleObj.selector || selector === "**" && handleObj.selector)) {
            handlers.splice(j, 1);
            if (handleObj.selector) {
              handlers.delegateCount--;
            }
            if (special.remove) {
              special.remove.call(elem, handleObj);
            }
          }
        }
        if (origCount && !handlers.length) {
          if (!special.teardown || special.teardown.call(elem, namespaces, elemData.handle) === false) {
            jQuery.removeEvent(elem, type, elemData.handle);
          }
          delete events[type];
        }
      }
      if (jQuery.isEmptyObject(events)) {
        delete elemData.handle;
        data_priv.remove(elem, "events");
      }
    },
    trigger: function(event, data, elem, onlyHandlers) {
      var i,
          cur,
          tmp,
          bubbleType,
          ontype,
          handle,
          special,
          eventPath = [elem || document],
          type = hasOwn.call(event, "type") ? event.type : event,
          namespaces = hasOwn.call(event, "namespace") ? event.namespace.split(".") : [];
      cur = tmp = elem = elem || document;
      if (elem.nodeType === 3 || elem.nodeType === 8) {
        return;
      }
      if (rfocusMorph.test(type + jQuery.event.triggered)) {
        return;
      }
      if (type.indexOf(".") >= 0) {
        namespaces = type.split(".");
        type = namespaces.shift();
        namespaces.sort();
      }
      ontype = type.indexOf(":") < 0 && "on" + type;
      event = event[jQuery.expando] ? event : new jQuery.Event(type, typeof event === "object" && event);
      event.isTrigger = onlyHandlers ? 2 : 3;
      event.namespace = namespaces.join(".");
      event.namespace_re = event.namespace ? new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)") : null;
      event.result = undefined;
      if (!event.target) {
        event.target = elem;
      }
      data = data == null ? [event] : jQuery.makeArray(data, [event]);
      special = jQuery.event.special[type] || {};
      if (!onlyHandlers && special.trigger && special.trigger.apply(elem, data) === false) {
        return;
      }
      if (!onlyHandlers && !special.noBubble && !jQuery.isWindow(elem)) {
        bubbleType = special.delegateType || type;
        if (!rfocusMorph.test(bubbleType + type)) {
          cur = cur.parentNode;
        }
        for (; cur; cur = cur.parentNode) {
          eventPath.push(cur);
          tmp = cur;
        }
        if (tmp === (elem.ownerDocument || document)) {
          eventPath.push(tmp.defaultView || tmp.parentWindow || window);
        }
      }
      i = 0;
      while ((cur = eventPath[i++]) && !event.isPropagationStopped()) {
        event.type = i > 1 ? bubbleType : special.bindType || type;
        handle = (data_priv.get(cur, "events") || {})[event.type] && data_priv.get(cur, "handle");
        if (handle) {
          handle.apply(cur, data);
        }
        handle = ontype && cur[ontype];
        if (handle && handle.apply && jQuery.acceptData(cur)) {
          event.result = handle.apply(cur, data);
          if (event.result === false) {
            event.preventDefault();
          }
        }
      }
      event.type = type;
      if (!onlyHandlers && !event.isDefaultPrevented()) {
        if ((!special._default || special._default.apply(eventPath.pop(), data) === false) && jQuery.acceptData(elem)) {
          if (ontype && jQuery.isFunction(elem[type]) && !jQuery.isWindow(elem)) {
            tmp = elem[ontype];
            if (tmp) {
              elem[ontype] = null;
            }
            jQuery.event.triggered = type;
            elem[type]();
            jQuery.event.triggered = undefined;
            if (tmp) {
              elem[ontype] = tmp;
            }
          }
        }
      }
      return event.result;
    },
    dispatch: function(event) {
      event = jQuery.event.fix(event);
      var i,
          j,
          ret,
          matched,
          handleObj,
          handlerQueue = [],
          args = slice.call(arguments),
          handlers = (data_priv.get(this, "events") || {})[event.type] || [],
          special = jQuery.event.special[event.type] || {};
      args[0] = event;
      event.delegateTarget = this;
      if (special.preDispatch && special.preDispatch.call(this, event) === false) {
        return;
      }
      handlerQueue = jQuery.event.handlers.call(this, event, handlers);
      i = 0;
      while ((matched = handlerQueue[i++]) && !event.isPropagationStopped()) {
        event.currentTarget = matched.elem;
        j = 0;
        while ((handleObj = matched.handlers[j++]) && !event.isImmediatePropagationStopped()) {
          if (!event.namespace_re || event.namespace_re.test(handleObj.namespace)) {
            event.handleObj = handleObj;
            event.data = handleObj.data;
            ret = ((jQuery.event.special[handleObj.origType] || {}).handle || handleObj.handler).apply(matched.elem, args);
            if (ret !== undefined) {
              if ((event.result = ret) === false) {
                event.preventDefault();
                event.stopPropagation();
              }
            }
          }
        }
      }
      if (special.postDispatch) {
        special.postDispatch.call(this, event);
      }
      return event.result;
    },
    handlers: function(event, handlers) {
      var i,
          matches,
          sel,
          handleObj,
          handlerQueue = [],
          delegateCount = handlers.delegateCount,
          cur = event.target;
      if (delegateCount && cur.nodeType && (!event.button || event.type !== "click")) {
        for (; cur !== this; cur = cur.parentNode || this) {
          if (cur.disabled !== true || event.type !== "click") {
            matches = [];
            for (i = 0; i < delegateCount; i++) {
              handleObj = handlers[i];
              sel = handleObj.selector + " ";
              if (matches[sel] === undefined) {
                matches[sel] = handleObj.needsContext ? jQuery(sel, this).index(cur) >= 0 : jQuery.find(sel, this, null, [cur]).length;
              }
              if (matches[sel]) {
                matches.push(handleObj);
              }
            }
            if (matches.length) {
              handlerQueue.push({
                elem: cur,
                handlers: matches
              });
            }
          }
        }
      }
      if (delegateCount < handlers.length) {
        handlerQueue.push({
          elem: this,
          handlers: handlers.slice(delegateCount)
        });
      }
      return handlerQueue;
    },
    props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
    fixHooks: {},
    keyHooks: {
      props: "char charCode key keyCode".split(" "),
      filter: function(event, original) {
        if (event.which == null) {
          event.which = original.charCode != null ? original.charCode : original.keyCode;
        }
        return event;
      }
    },
    mouseHooks: {
      props: "button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
      filter: function(event, original) {
        var eventDoc,
            doc,
            body,
            button = original.button;
        if (event.pageX == null && original.clientX != null) {
          eventDoc = event.target.ownerDocument || document;
          doc = eventDoc.documentElement;
          body = eventDoc.body;
          event.pageX = original.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
          event.pageY = original.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);
        }
        if (!event.which && button !== undefined) {
          event.which = (button & 1 ? 1 : (button & 2 ? 3 : (button & 4 ? 2 : 0)));
        }
        return event;
      }
    },
    fix: function(event) {
      if (event[jQuery.expando]) {
        return event;
      }
      var i,
          prop,
          copy,
          type = event.type,
          originalEvent = event,
          fixHook = this.fixHooks[type];
      if (!fixHook) {
        this.fixHooks[type] = fixHook = rmouseEvent.test(type) ? this.mouseHooks : rkeyEvent.test(type) ? this.keyHooks : {};
      }
      copy = fixHook.props ? this.props.concat(fixHook.props) : this.props;
      event = new jQuery.Event(originalEvent);
      i = copy.length;
      while (i--) {
        prop = copy[i];
        event[prop] = originalEvent[prop];
      }
      if (!event.target) {
        event.target = document;
      }
      if (event.target.nodeType === 3) {
        event.target = event.target.parentNode;
      }
      return fixHook.filter ? fixHook.filter(event, originalEvent) : event;
    },
    special: {
      load: {noBubble: true},
      focus: {
        trigger: function() {
          if (this !== safeActiveElement() && this.focus) {
            this.focus();
            return false;
          }
        },
        delegateType: "focusin"
      },
      blur: {
        trigger: function() {
          if (this === safeActiveElement() && this.blur) {
            this.blur();
            return false;
          }
        },
        delegateType: "focusout"
      },
      click: {
        trigger: function() {
          if (this.type === "checkbox" && this.click && jQuery.nodeName(this, "input")) {
            this.click();
            return false;
          }
        },
        _default: function(event) {
          return jQuery.nodeName(event.target, "a");
        }
      },
      beforeunload: {postDispatch: function(event) {
          if (event.result !== undefined && event.originalEvent) {
            event.originalEvent.returnValue = event.result;
          }
        }}
    },
    simulate: function(type, elem, event, bubble) {
      var e = jQuery.extend(new jQuery.Event(), event, {
        type: type,
        isSimulated: true,
        originalEvent: {}
      });
      if (bubble) {
        jQuery.event.trigger(e, null, elem);
      } else {
        jQuery.event.dispatch.call(elem, e);
      }
      if (e.isDefaultPrevented()) {
        event.preventDefault();
      }
    }
  };
  jQuery.removeEvent = function(elem, type, handle) {
    if (elem.removeEventListener) {
      elem.removeEventListener(type, handle, false);
    }
  };
  jQuery.Event = function(src, props) {
    if (!(this instanceof jQuery.Event)) {
      return new jQuery.Event(src, props);
    }
    if (src && src.type) {
      this.originalEvent = src;
      this.type = src.type;
      this.isDefaultPrevented = src.defaultPrevented || src.defaultPrevented === undefined && src.returnValue === false ? returnTrue : returnFalse;
    } else {
      this.type = src;
    }
    if (props) {
      jQuery.extend(this, props);
    }
    this.timeStamp = src && src.timeStamp || jQuery.now();
    this[jQuery.expando] = true;
  };
  jQuery.Event.prototype = {
    isDefaultPrevented: returnFalse,
    isPropagationStopped: returnFalse,
    isImmediatePropagationStopped: returnFalse,
    preventDefault: function() {
      var e = this.originalEvent;
      this.isDefaultPrevented = returnTrue;
      if (e && e.preventDefault) {
        e.preventDefault();
      }
    },
    stopPropagation: function() {
      var e = this.originalEvent;
      this.isPropagationStopped = returnTrue;
      if (e && e.stopPropagation) {
        e.stopPropagation();
      }
    },
    stopImmediatePropagation: function() {
      var e = this.originalEvent;
      this.isImmediatePropagationStopped = returnTrue;
      if (e && e.stopImmediatePropagation) {
        e.stopImmediatePropagation();
      }
      this.stopPropagation();
    }
  };
  jQuery.each({
    mouseenter: "mouseover",
    mouseleave: "mouseout",
    pointerenter: "pointerover",
    pointerleave: "pointerout"
  }, function(orig, fix) {
    jQuery.event.special[orig] = {
      delegateType: fix,
      bindType: fix,
      handle: function(event) {
        var ret,
            target = this,
            related = event.relatedTarget,
            handleObj = event.handleObj;
        if (!related || (related !== target && !jQuery.contains(target, related))) {
          event.type = handleObj.origType;
          ret = handleObj.handler.apply(this, arguments);
          event.type = fix;
        }
        return ret;
      }
    };
  });
  if (!support.focusinBubbles) {
    jQuery.each({
      focus: "focusin",
      blur: "focusout"
    }, function(orig, fix) {
      var handler = function(event) {
        jQuery.event.simulate(fix, event.target, jQuery.event.fix(event), true);
      };
      jQuery.event.special[fix] = {
        setup: function() {
          var doc = this.ownerDocument || this,
              attaches = data_priv.access(doc, fix);
          if (!attaches) {
            doc.addEventListener(orig, handler, true);
          }
          data_priv.access(doc, fix, (attaches || 0) + 1);
        },
        teardown: function() {
          var doc = this.ownerDocument || this,
              attaches = data_priv.access(doc, fix) - 1;
          if (!attaches) {
            doc.removeEventListener(orig, handler, true);
            data_priv.remove(doc, fix);
          } else {
            data_priv.access(doc, fix, attaches);
          }
        }
      };
    });
  }
  jQuery.fn.extend({
    on: function(types, selector, data, fn, one) {
      var origFn,
          type;
      if (typeof types === "object") {
        if (typeof selector !== "string") {
          data = data || selector;
          selector = undefined;
        }
        for (type in types) {
          this.on(type, selector, data, types[type], one);
        }
        return this;
      }
      if (data == null && fn == null) {
        fn = selector;
        data = selector = undefined;
      } else if (fn == null) {
        if (typeof selector === "string") {
          fn = data;
          data = undefined;
        } else {
          fn = data;
          data = selector;
          selector = undefined;
        }
      }
      if (fn === false) {
        fn = returnFalse;
      } else if (!fn) {
        return this;
      }
      if (one === 1) {
        origFn = fn;
        fn = function(event) {
          jQuery().off(event);
          return origFn.apply(this, arguments);
        };
        fn.guid = origFn.guid || (origFn.guid = jQuery.guid++);
      }
      return this.each(function() {
        jQuery.event.add(this, types, fn, data, selector);
      });
    },
    one: function(types, selector, data, fn) {
      return this.on(types, selector, data, fn, 1);
    },
    off: function(types, selector, fn) {
      var handleObj,
          type;
      if (types && types.preventDefault && types.handleObj) {
        handleObj = types.handleObj;
        jQuery(types.delegateTarget).off(handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, handleObj.selector, handleObj.handler);
        return this;
      }
      if (typeof types === "object") {
        for (type in types) {
          this.off(type, selector, types[type]);
        }
        return this;
      }
      if (selector === false || typeof selector === "function") {
        fn = selector;
        selector = undefined;
      }
      if (fn === false) {
        fn = returnFalse;
      }
      return this.each(function() {
        jQuery.event.remove(this, types, fn, selector);
      });
    },
    trigger: function(type, data) {
      return this.each(function() {
        jQuery.event.trigger(type, data, this);
      });
    },
    triggerHandler: function(type, data) {
      var elem = this[0];
      if (elem) {
        return jQuery.event.trigger(type, data, elem, true);
      }
    }
  });
  var rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
      rtagName = /<([\w:]+)/,
      rhtml = /<|&#?\w+;/,
      rnoInnerhtml = /<(?:script|style|link)/i,
      rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
      rscriptType = /^$|\/(?:java|ecma)script/i,
      rscriptTypeMasked = /^true\/(.*)/,
      rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,
      wrapMap = {
        option: [1, "<select multiple='multiple'>", "</select>"],
        thead: [1, "<table>", "</table>"],
        col: [2, "<table><colgroup>", "</colgroup></table>"],
        tr: [2, "<table><tbody>", "</tbody></table>"],
        td: [3, "<table><tbody><tr>", "</tr></tbody></table>"],
        _default: [0, "", ""]
      };
  wrapMap.optgroup = wrapMap.option;
  wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
  wrapMap.th = wrapMap.td;
  function manipulationTarget(elem, content) {
    return jQuery.nodeName(elem, "table") && jQuery.nodeName(content.nodeType !== 11 ? content : content.firstChild, "tr") ? elem.getElementsByTagName("tbody")[0] || elem.appendChild(elem.ownerDocument.createElement("tbody")) : elem;
  }
  function disableScript(elem) {
    elem.type = (elem.getAttribute("type") !== null) + "/" + elem.type;
    return elem;
  }
  function restoreScript(elem) {
    var match = rscriptTypeMasked.exec(elem.type);
    if (match) {
      elem.type = match[1];
    } else {
      elem.removeAttribute("type");
    }
    return elem;
  }
  function setGlobalEval(elems, refElements) {
    var i = 0,
        l = elems.length;
    for (; i < l; i++) {
      data_priv.set(elems[i], "globalEval", !refElements || data_priv.get(refElements[i], "globalEval"));
    }
  }
  function cloneCopyEvent(src, dest) {
    var i,
        l,
        type,
        pdataOld,
        pdataCur,
        udataOld,
        udataCur,
        events;
    if (dest.nodeType !== 1) {
      return;
    }
    if (data_priv.hasData(src)) {
      pdataOld = data_priv.access(src);
      pdataCur = data_priv.set(dest, pdataOld);
      events = pdataOld.events;
      if (events) {
        delete pdataCur.handle;
        pdataCur.events = {};
        for (type in events) {
          for (i = 0, l = events[type].length; i < l; i++) {
            jQuery.event.add(dest, type, events[type][i]);
          }
        }
      }
    }
    if (data_user.hasData(src)) {
      udataOld = data_user.access(src);
      udataCur = jQuery.extend({}, udataOld);
      data_user.set(dest, udataCur);
    }
  }
  function getAll(context, tag) {
    var ret = context.getElementsByTagName ? context.getElementsByTagName(tag || "*") : context.querySelectorAll ? context.querySelectorAll(tag || "*") : [];
    return tag === undefined || tag && jQuery.nodeName(context, tag) ? jQuery.merge([context], ret) : ret;
  }
  function fixInput(src, dest) {
    var nodeName = dest.nodeName.toLowerCase();
    if (nodeName === "input" && rcheckableType.test(src.type)) {
      dest.checked = src.checked;
    } else if (nodeName === "input" || nodeName === "textarea") {
      dest.defaultValue = src.defaultValue;
    }
  }
  jQuery.extend({
    clone: function(elem, dataAndEvents, deepDataAndEvents) {
      var i,
          l,
          srcElements,
          destElements,
          clone = elem.cloneNode(true),
          inPage = jQuery.contains(elem.ownerDocument, elem);
      if (!support.noCloneChecked && (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem)) {
        destElements = getAll(clone);
        srcElements = getAll(elem);
        for (i = 0, l = srcElements.length; i < l; i++) {
          fixInput(srcElements[i], destElements[i]);
        }
      }
      if (dataAndEvents) {
        if (deepDataAndEvents) {
          srcElements = srcElements || getAll(elem);
          destElements = destElements || getAll(clone);
          for (i = 0, l = srcElements.length; i < l; i++) {
            cloneCopyEvent(srcElements[i], destElements[i]);
          }
        } else {
          cloneCopyEvent(elem, clone);
        }
      }
      destElements = getAll(clone, "script");
      if (destElements.length > 0) {
        setGlobalEval(destElements, !inPage && getAll(elem, "script"));
      }
      return clone;
    },
    buildFragment: function(elems, context, scripts, selection) {
      var elem,
          tmp,
          tag,
          wrap,
          contains,
          j,
          fragment = context.createDocumentFragment(),
          nodes = [],
          i = 0,
          l = elems.length;
      for (; i < l; i++) {
        elem = elems[i];
        if (elem || elem === 0) {
          if (jQuery.type(elem) === "object") {
            jQuery.merge(nodes, elem.nodeType ? [elem] : elem);
          } else if (!rhtml.test(elem)) {
            nodes.push(context.createTextNode(elem));
          } else {
            tmp = tmp || fragment.appendChild(context.createElement("div"));
            tag = (rtagName.exec(elem) || ["", ""])[1].toLowerCase();
            wrap = wrapMap[tag] || wrapMap._default;
            tmp.innerHTML = wrap[1] + elem.replace(rxhtmlTag, "<$1></$2>") + wrap[2];
            j = wrap[0];
            while (j--) {
              tmp = tmp.lastChild;
            }
            jQuery.merge(nodes, tmp.childNodes);
            tmp = fragment.firstChild;
            tmp.textContent = "";
          }
        }
      }
      fragment.textContent = "";
      i = 0;
      while ((elem = nodes[i++])) {
        if (selection && jQuery.inArray(elem, selection) !== -1) {
          continue;
        }
        contains = jQuery.contains(elem.ownerDocument, elem);
        tmp = getAll(fragment.appendChild(elem), "script");
        if (contains) {
          setGlobalEval(tmp);
        }
        if (scripts) {
          j = 0;
          while ((elem = tmp[j++])) {
            if (rscriptType.test(elem.type || "")) {
              scripts.push(elem);
            }
          }
        }
      }
      return fragment;
    },
    cleanData: function(elems) {
      var data,
          elem,
          type,
          key,
          special = jQuery.event.special,
          i = 0;
      for (; (elem = elems[i]) !== undefined; i++) {
        if (jQuery.acceptData(elem)) {
          key = elem[data_priv.expando];
          if (key && (data = data_priv.cache[key])) {
            if (data.events) {
              for (type in data.events) {
                if (special[type]) {
                  jQuery.event.remove(elem, type);
                } else {
                  jQuery.removeEvent(elem, type, data.handle);
                }
              }
            }
            if (data_priv.cache[key]) {
              delete data_priv.cache[key];
            }
          }
        }
        delete data_user.cache[elem[data_user.expando]];
      }
    }
  });
  jQuery.fn.extend({
    text: function(value) {
      return access(this, function(value) {
        return value === undefined ? jQuery.text(this) : this.empty().each(function() {
          if (this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9) {
            this.textContent = value;
          }
        });
      }, null, value, arguments.length);
    },
    append: function() {
      return this.domManip(arguments, function(elem) {
        if (this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9) {
          var target = manipulationTarget(this, elem);
          target.appendChild(elem);
        }
      });
    },
    prepend: function() {
      return this.domManip(arguments, function(elem) {
        if (this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9) {
          var target = manipulationTarget(this, elem);
          target.insertBefore(elem, target.firstChild);
        }
      });
    },
    before: function() {
      return this.domManip(arguments, function(elem) {
        if (this.parentNode) {
          this.parentNode.insertBefore(elem, this);
        }
      });
    },
    after: function() {
      return this.domManip(arguments, function(elem) {
        if (this.parentNode) {
          this.parentNode.insertBefore(elem, this.nextSibling);
        }
      });
    },
    remove: function(selector, keepData) {
      var elem,
          elems = selector ? jQuery.filter(selector, this) : this,
          i = 0;
      for (; (elem = elems[i]) != null; i++) {
        if (!keepData && elem.nodeType === 1) {
          jQuery.cleanData(getAll(elem));
        }
        if (elem.parentNode) {
          if (keepData && jQuery.contains(elem.ownerDocument, elem)) {
            setGlobalEval(getAll(elem, "script"));
          }
          elem.parentNode.removeChild(elem);
        }
      }
      return this;
    },
    empty: function() {
      var elem,
          i = 0;
      for (; (elem = this[i]) != null; i++) {
        if (elem.nodeType === 1) {
          jQuery.cleanData(getAll(elem, false));
          elem.textContent = "";
        }
      }
      return this;
    },
    clone: function(dataAndEvents, deepDataAndEvents) {
      dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
      deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
      return this.map(function() {
        return jQuery.clone(this, dataAndEvents, deepDataAndEvents);
      });
    },
    html: function(value) {
      return access(this, function(value) {
        var elem = this[0] || {},
            i = 0,
            l = this.length;
        if (value === undefined && elem.nodeType === 1) {
          return elem.innerHTML;
        }
        if (typeof value === "string" && !rnoInnerhtml.test(value) && !wrapMap[(rtagName.exec(value) || ["", ""])[1].toLowerCase()]) {
          value = value.replace(rxhtmlTag, "<$1></$2>");
          try {
            for (; i < l; i++) {
              elem = this[i] || {};
              if (elem.nodeType === 1) {
                jQuery.cleanData(getAll(elem, false));
                elem.innerHTML = value;
              }
            }
            elem = 0;
          } catch (e) {}
        }
        if (elem) {
          this.empty().append(value);
        }
      }, null, value, arguments.length);
    },
    replaceWith: function() {
      var arg = arguments[0];
      this.domManip(arguments, function(elem) {
        arg = this.parentNode;
        jQuery.cleanData(getAll(this));
        if (arg) {
          arg.replaceChild(elem, this);
        }
      });
      return arg && (arg.length || arg.nodeType) ? this : this.remove();
    },
    detach: function(selector) {
      return this.remove(selector, true);
    },
    domManip: function(args, callback) {
      args = concat.apply([], args);
      var fragment,
          first,
          scripts,
          hasScripts,
          node,
          doc,
          i = 0,
          l = this.length,
          set = this,
          iNoClone = l - 1,
          value = args[0],
          isFunction = jQuery.isFunction(value);
      if (isFunction || (l > 1 && typeof value === "string" && !support.checkClone && rchecked.test(value))) {
        return this.each(function(index) {
          var self = set.eq(index);
          if (isFunction) {
            args[0] = value.call(this, index, self.html());
          }
          self.domManip(args, callback);
        });
      }
      if (l) {
        fragment = jQuery.buildFragment(args, this[0].ownerDocument, false, this);
        first = fragment.firstChild;
        if (fragment.childNodes.length === 1) {
          fragment = first;
        }
        if (first) {
          scripts = jQuery.map(getAll(fragment, "script"), disableScript);
          hasScripts = scripts.length;
          for (; i < l; i++) {
            node = fragment;
            if (i !== iNoClone) {
              node = jQuery.clone(node, true, true);
              if (hasScripts) {
                jQuery.merge(scripts, getAll(node, "script"));
              }
            }
            callback.call(this[i], node, i);
          }
          if (hasScripts) {
            doc = scripts[scripts.length - 1].ownerDocument;
            jQuery.map(scripts, restoreScript);
            for (i = 0; i < hasScripts; i++) {
              node = scripts[i];
              if (rscriptType.test(node.type || "") && !data_priv.access(node, "globalEval") && jQuery.contains(doc, node)) {
                if (node.src) {
                  if (jQuery._evalUrl) {
                    jQuery._evalUrl(node.src);
                  }
                } else {
                  jQuery.globalEval(node.textContent.replace(rcleanScript, ""));
                }
              }
            }
          }
        }
      }
      return this;
    }
  });
  jQuery.each({
    appendTo: "append",
    prependTo: "prepend",
    insertBefore: "before",
    insertAfter: "after",
    replaceAll: "replaceWith"
  }, function(name, original) {
    jQuery.fn[name] = function(selector) {
      var elems,
          ret = [],
          insert = jQuery(selector),
          last = insert.length - 1,
          i = 0;
      for (; i <= last; i++) {
        elems = i === last ? this : this.clone(true);
        jQuery(insert[i])[original](elems);
        push.apply(ret, elems.get());
      }
      return this.pushStack(ret);
    };
  });
  var iframe,
      elemdisplay = {};
  function actualDisplay(name, doc) {
    var style,
        elem = jQuery(doc.createElement(name)).appendTo(doc.body),
        display = window.getDefaultComputedStyle && (style = window.getDefaultComputedStyle(elem[0])) ? style.display : jQuery.css(elem[0], "display");
    elem.detach();
    return display;
  }
  function defaultDisplay(nodeName) {
    var doc = document,
        display = elemdisplay[nodeName];
    if (!display) {
      display = actualDisplay(nodeName, doc);
      if (display === "none" || !display) {
        iframe = (iframe || jQuery("<iframe frameborder='0' width='0' height='0'/>")).appendTo(doc.documentElement);
        doc = iframe[0].contentDocument;
        doc.write();
        doc.close();
        display = actualDisplay(nodeName, doc);
        iframe.detach();
      }
      elemdisplay[nodeName] = display;
    }
    return display;
  }
  var rmargin = (/^margin/);
  var rnumnonpx = new RegExp("^(" + pnum + ")(?!px)[a-z%]+$", "i");
  var getStyles = function(elem) {
    if (elem.ownerDocument.defaultView.opener) {
      return elem.ownerDocument.defaultView.getComputedStyle(elem, null);
    }
    return window.getComputedStyle(elem, null);
  };
  function curCSS(elem, name, computed) {
    var width,
        minWidth,
        maxWidth,
        ret,
        style = elem.style;
    computed = computed || getStyles(elem);
    if (computed) {
      ret = computed.getPropertyValue(name) || computed[name];
    }
    if (computed) {
      if (ret === "" && !jQuery.contains(elem.ownerDocument, elem)) {
        ret = jQuery.style(elem, name);
      }
      if (rnumnonpx.test(ret) && rmargin.test(name)) {
        width = style.width;
        minWidth = style.minWidth;
        maxWidth = style.maxWidth;
        style.minWidth = style.maxWidth = style.width = ret;
        ret = computed.width;
        style.width = width;
        style.minWidth = minWidth;
        style.maxWidth = maxWidth;
      }
    }
    return ret !== undefined ? ret + "" : ret;
  }
  function addGetHookIf(conditionFn, hookFn) {
    return {get: function() {
        if (conditionFn()) {
          delete this.get;
          return;
        }
        return (this.get = hookFn).apply(this, arguments);
      }};
  }
  (function() {
    var pixelPositionVal,
        boxSizingReliableVal,
        docElem = document.documentElement,
        container = document.createElement("div"),
        div = document.createElement("div");
    if (!div.style) {
      return;
    }
    div.style.backgroundClip = "content-box";
    div.cloneNode(true).style.backgroundClip = "";
    support.clearCloneStyle = div.style.backgroundClip === "content-box";
    container.style.cssText = "border:0;width:0;height:0;top:0;left:-9999px;margin-top:1px;" + "position:absolute";
    container.appendChild(div);
    function computePixelPositionAndBoxSizingReliable() {
      div.style.cssText = "-webkit-box-sizing:border-box;-moz-box-sizing:border-box;" + "box-sizing:border-box;display:block;margin-top:1%;top:1%;" + "border:1px;padding:1px;width:4px;position:absolute";
      div.innerHTML = "";
      docElem.appendChild(container);
      var divStyle = window.getComputedStyle(div, null);
      pixelPositionVal = divStyle.top !== "1%";
      boxSizingReliableVal = divStyle.width === "4px";
      docElem.removeChild(container);
    }
    if (window.getComputedStyle) {
      jQuery.extend(support, {
        pixelPosition: function() {
          computePixelPositionAndBoxSizingReliable();
          return pixelPositionVal;
        },
        boxSizingReliable: function() {
          if (boxSizingReliableVal == null) {
            computePixelPositionAndBoxSizingReliable();
          }
          return boxSizingReliableVal;
        },
        reliableMarginRight: function() {
          var ret,
              marginDiv = div.appendChild(document.createElement("div"));
          marginDiv.style.cssText = div.style.cssText = "-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" + "box-sizing:content-box;display:block;margin:0;border:0;padding:0";
          marginDiv.style.marginRight = marginDiv.style.width = "0";
          div.style.width = "1px";
          docElem.appendChild(container);
          ret = !parseFloat(window.getComputedStyle(marginDiv, null).marginRight);
          docElem.removeChild(container);
          div.removeChild(marginDiv);
          return ret;
        }
      });
    }
  })();
  jQuery.swap = function(elem, options, callback, args) {
    var ret,
        name,
        old = {};
    for (name in options) {
      old[name] = elem.style[name];
      elem.style[name] = options[name];
    }
    ret = callback.apply(elem, args || []);
    for (name in options) {
      elem.style[name] = old[name];
    }
    return ret;
  };
  var rdisplayswap = /^(none|table(?!-c[ea]).+)/,
      rnumsplit = new RegExp("^(" + pnum + ")(.*)$", "i"),
      rrelNum = new RegExp("^([+-])=(" + pnum + ")", "i"),
      cssShow = {
        position: "absolute",
        visibility: "hidden",
        display: "block"
      },
      cssNormalTransform = {
        letterSpacing: "0",
        fontWeight: "400"
      },
      cssPrefixes = ["Webkit", "O", "Moz", "ms"];
  function vendorPropName(style, name) {
    if (name in style) {
      return name;
    }
    var capName = name[0].toUpperCase() + name.slice(1),
        origName = name,
        i = cssPrefixes.length;
    while (i--) {
      name = cssPrefixes[i] + capName;
      if (name in style) {
        return name;
      }
    }
    return origName;
  }
  function setPositiveNumber(elem, value, subtract) {
    var matches = rnumsplit.exec(value);
    return matches ? Math.max(0, matches[1] - (subtract || 0)) + (matches[2] || "px") : value;
  }
  function augmentWidthOrHeight(elem, name, extra, isBorderBox, styles) {
    var i = extra === (isBorderBox ? "border" : "content") ? 4 : name === "width" ? 1 : 0,
        val = 0;
    for (; i < 4; i += 2) {
      if (extra === "margin") {
        val += jQuery.css(elem, extra + cssExpand[i], true, styles);
      }
      if (isBorderBox) {
        if (extra === "content") {
          val -= jQuery.css(elem, "padding" + cssExpand[i], true, styles);
        }
        if (extra !== "margin") {
          val -= jQuery.css(elem, "border" + cssExpand[i] + "Width", true, styles);
        }
      } else {
        val += jQuery.css(elem, "padding" + cssExpand[i], true, styles);
        if (extra !== "padding") {
          val += jQuery.css(elem, "border" + cssExpand[i] + "Width", true, styles);
        }
      }
    }
    return val;
  }
  function getWidthOrHeight(elem, name, extra) {
    var valueIsBorderBox = true,
        val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
        styles = getStyles(elem),
        isBorderBox = jQuery.css(elem, "boxSizing", false, styles) === "border-box";
    if (val <= 0 || val == null) {
      val = curCSS(elem, name, styles);
      if (val < 0 || val == null) {
        val = elem.style[name];
      }
      if (rnumnonpx.test(val)) {
        return val;
      }
      valueIsBorderBox = isBorderBox && (support.boxSizingReliable() || val === elem.style[name]);
      val = parseFloat(val) || 0;
    }
    return (val + augmentWidthOrHeight(elem, name, extra || (isBorderBox ? "border" : "content"), valueIsBorderBox, styles)) + "px";
  }
  function showHide(elements, show) {
    var display,
        elem,
        hidden,
        values = [],
        index = 0,
        length = elements.length;
    for (; index < length; index++) {
      elem = elements[index];
      if (!elem.style) {
        continue;
      }
      values[index] = data_priv.get(elem, "olddisplay");
      display = elem.style.display;
      if (show) {
        if (!values[index] && display === "none") {
          elem.style.display = "";
        }
        if (elem.style.display === "" && isHidden(elem)) {
          values[index] = data_priv.access(elem, "olddisplay", defaultDisplay(elem.nodeName));
        }
      } else {
        hidden = isHidden(elem);
        if (display !== "none" || !hidden) {
          data_priv.set(elem, "olddisplay", hidden ? display : jQuery.css(elem, "display"));
        }
      }
    }
    for (index = 0; index < length; index++) {
      elem = elements[index];
      if (!elem.style) {
        continue;
      }
      if (!show || elem.style.display === "none" || elem.style.display === "") {
        elem.style.display = show ? values[index] || "" : "none";
      }
    }
    return elements;
  }
  jQuery.extend({
    cssHooks: {opacity: {get: function(elem, computed) {
          if (computed) {
            var ret = curCSS(elem, "opacity");
            return ret === "" ? "1" : ret;
          }
        }}},
    cssNumber: {
      "columnCount": true,
      "fillOpacity": true,
      "flexGrow": true,
      "flexShrink": true,
      "fontWeight": true,
      "lineHeight": true,
      "opacity": true,
      "order": true,
      "orphans": true,
      "widows": true,
      "zIndex": true,
      "zoom": true
    },
    cssProps: {"float": "cssFloat"},
    style: function(elem, name, value, extra) {
      if (!elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style) {
        return;
      }
      var ret,
          type,
          hooks,
          origName = jQuery.camelCase(name),
          style = elem.style;
      name = jQuery.cssProps[origName] || (jQuery.cssProps[origName] = vendorPropName(style, origName));
      hooks = jQuery.cssHooks[name] || jQuery.cssHooks[origName];
      if (value !== undefined) {
        type = typeof value;
        if (type === "string" && (ret = rrelNum.exec(value))) {
          value = (ret[1] + 1) * ret[2] + parseFloat(jQuery.css(elem, name));
          type = "number";
        }
        if (value == null || value !== value) {
          return;
        }
        if (type === "number" && !jQuery.cssNumber[origName]) {
          value += "px";
        }
        if (!support.clearCloneStyle && value === "" && name.indexOf("background") === 0) {
          style[name] = "inherit";
        }
        if (!hooks || !("set" in hooks) || (value = hooks.set(elem, value, extra)) !== undefined) {
          style[name] = value;
        }
      } else {
        if (hooks && "get" in hooks && (ret = hooks.get(elem, false, extra)) !== undefined) {
          return ret;
        }
        return style[name];
      }
    },
    css: function(elem, name, extra, styles) {
      var val,
          num,
          hooks,
          origName = jQuery.camelCase(name);
      name = jQuery.cssProps[origName] || (jQuery.cssProps[origName] = vendorPropName(elem.style, origName));
      hooks = jQuery.cssHooks[name] || jQuery.cssHooks[origName];
      if (hooks && "get" in hooks) {
        val = hooks.get(elem, true, extra);
      }
      if (val === undefined) {
        val = curCSS(elem, name, styles);
      }
      if (val === "normal" && name in cssNormalTransform) {
        val = cssNormalTransform[name];
      }
      if (extra === "" || extra) {
        num = parseFloat(val);
        return extra === true || jQuery.isNumeric(num) ? num || 0 : val;
      }
      return val;
    }
  });
  jQuery.each(["height", "width"], function(i, name) {
    jQuery.cssHooks[name] = {
      get: function(elem, computed, extra) {
        if (computed) {
          return rdisplayswap.test(jQuery.css(elem, "display")) && elem.offsetWidth === 0 ? jQuery.swap(elem, cssShow, function() {
            return getWidthOrHeight(elem, name, extra);
          }) : getWidthOrHeight(elem, name, extra);
        }
      },
      set: function(elem, value, extra) {
        var styles = extra && getStyles(elem);
        return setPositiveNumber(elem, value, extra ? augmentWidthOrHeight(elem, name, extra, jQuery.css(elem, "boxSizing", false, styles) === "border-box", styles) : 0);
      }
    };
  });
  jQuery.cssHooks.marginRight = addGetHookIf(support.reliableMarginRight, function(elem, computed) {
    if (computed) {
      return jQuery.swap(elem, {"display": "inline-block"}, curCSS, [elem, "marginRight"]);
    }
  });
  jQuery.each({
    margin: "",
    padding: "",
    border: "Width"
  }, function(prefix, suffix) {
    jQuery.cssHooks[prefix + suffix] = {expand: function(value) {
        var i = 0,
            expanded = {},
            parts = typeof value === "string" ? value.split(" ") : [value];
        for (; i < 4; i++) {
          expanded[prefix + cssExpand[i] + suffix] = parts[i] || parts[i - 2] || parts[0];
        }
        return expanded;
      }};
    if (!rmargin.test(prefix)) {
      jQuery.cssHooks[prefix + suffix].set = setPositiveNumber;
    }
  });
  jQuery.fn.extend({
    css: function(name, value) {
      return access(this, function(elem, name, value) {
        var styles,
            len,
            map = {},
            i = 0;
        if (jQuery.isArray(name)) {
          styles = getStyles(elem);
          len = name.length;
          for (; i < len; i++) {
            map[name[i]] = jQuery.css(elem, name[i], false, styles);
          }
          return map;
        }
        return value !== undefined ? jQuery.style(elem, name, value) : jQuery.css(elem, name);
      }, name, value, arguments.length > 1);
    },
    show: function() {
      return showHide(this, true);
    },
    hide: function() {
      return showHide(this);
    },
    toggle: function(state) {
      if (typeof state === "boolean") {
        return state ? this.show() : this.hide();
      }
      return this.each(function() {
        if (isHidden(this)) {
          jQuery(this).show();
        } else {
          jQuery(this).hide();
        }
      });
    }
  });
  function Tween(elem, options, prop, end, easing) {
    return new Tween.prototype.init(elem, options, prop, end, easing);
  }
  jQuery.Tween = Tween;
  Tween.prototype = {
    constructor: Tween,
    init: function(elem, options, prop, end, easing, unit) {
      this.elem = elem;
      this.prop = prop;
      this.easing = easing || "swing";
      this.options = options;
      this.start = this.now = this.cur();
      this.end = end;
      this.unit = unit || (jQuery.cssNumber[prop] ? "" : "px");
    },
    cur: function() {
      var hooks = Tween.propHooks[this.prop];
      return hooks && hooks.get ? hooks.get(this) : Tween.propHooks._default.get(this);
    },
    run: function(percent) {
      var eased,
          hooks = Tween.propHooks[this.prop];
      if (this.options.duration) {
        this.pos = eased = jQuery.easing[this.easing](percent, this.options.duration * percent, 0, 1, this.options.duration);
      } else {
        this.pos = eased = percent;
      }
      this.now = (this.end - this.start) * eased + this.start;
      if (this.options.step) {
        this.options.step.call(this.elem, this.now, this);
      }
      if (hooks && hooks.set) {
        hooks.set(this);
      } else {
        Tween.propHooks._default.set(this);
      }
      return this;
    }
  };
  Tween.prototype.init.prototype = Tween.prototype;
  Tween.propHooks = {_default: {
      get: function(tween) {
        var result;
        if (tween.elem[tween.prop] != null && (!tween.elem.style || tween.elem.style[tween.prop] == null)) {
          return tween.elem[tween.prop];
        }
        result = jQuery.css(tween.elem, tween.prop, "");
        return !result || result === "auto" ? 0 : result;
      },
      set: function(tween) {
        if (jQuery.fx.step[tween.prop]) {
          jQuery.fx.step[tween.prop](tween);
        } else if (tween.elem.style && (tween.elem.style[jQuery.cssProps[tween.prop]] != null || jQuery.cssHooks[tween.prop])) {
          jQuery.style(tween.elem, tween.prop, tween.now + tween.unit);
        } else {
          tween.elem[tween.prop] = tween.now;
        }
      }
    }};
  Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {set: function(tween) {
      if (tween.elem.nodeType && tween.elem.parentNode) {
        tween.elem[tween.prop] = tween.now;
      }
    }};
  jQuery.easing = {
    linear: function(p) {
      return p;
    },
    swing: function(p) {
      return 0.5 - Math.cos(p * Math.PI) / 2;
    }
  };
  jQuery.fx = Tween.prototype.init;
  jQuery.fx.step = {};
  var fxNow,
      timerId,
      rfxtypes = /^(?:toggle|show|hide)$/,
      rfxnum = new RegExp("^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i"),
      rrun = /queueHooks$/,
      animationPrefilters = [defaultPrefilter],
      tweeners = {"*": [function(prop, value) {
          var tween = this.createTween(prop, value),
              target = tween.cur(),
              parts = rfxnum.exec(value),
              unit = parts && parts[3] || (jQuery.cssNumber[prop] ? "" : "px"),
              start = (jQuery.cssNumber[prop] || unit !== "px" && +target) && rfxnum.exec(jQuery.css(tween.elem, prop)),
              scale = 1,
              maxIterations = 20;
          if (start && start[3] !== unit) {
            unit = unit || start[3];
            parts = parts || [];
            start = +target || 1;
            do {
              scale = scale || ".5";
              start = start / scale;
              jQuery.style(tween.elem, prop, start + unit);
            } while (scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations);
          }
          if (parts) {
            start = tween.start = +start || +target || 0;
            tween.unit = unit;
            tween.end = parts[1] ? start + (parts[1] + 1) * parts[2] : +parts[2];
          }
          return tween;
        }]};
  function createFxNow() {
    setTimeout(function() {
      fxNow = undefined;
    });
    return (fxNow = jQuery.now());
  }
  function genFx(type, includeWidth) {
    var which,
        i = 0,
        attrs = {height: type};
    includeWidth = includeWidth ? 1 : 0;
    for (; i < 4; i += 2 - includeWidth) {
      which = cssExpand[i];
      attrs["margin" + which] = attrs["padding" + which] = type;
    }
    if (includeWidth) {
      attrs.opacity = attrs.width = type;
    }
    return attrs;
  }
  function createTween(value, prop, animation) {
    var tween,
        collection = (tweeners[prop] || []).concat(tweeners["*"]),
        index = 0,
        length = collection.length;
    for (; index < length; index++) {
      if ((tween = collection[index].call(animation, prop, value))) {
        return tween;
      }
    }
  }
  function defaultPrefilter(elem, props, opts) {
    var prop,
        value,
        toggle,
        tween,
        hooks,
        oldfire,
        display,
        checkDisplay,
        anim = this,
        orig = {},
        style = elem.style,
        hidden = elem.nodeType && isHidden(elem),
        dataShow = data_priv.get(elem, "fxshow");
    if (!opts.queue) {
      hooks = jQuery._queueHooks(elem, "fx");
      if (hooks.unqueued == null) {
        hooks.unqueued = 0;
        oldfire = hooks.empty.fire;
        hooks.empty.fire = function() {
          if (!hooks.unqueued) {
            oldfire();
          }
        };
      }
      hooks.unqueued++;
      anim.always(function() {
        anim.always(function() {
          hooks.unqueued--;
          if (!jQuery.queue(elem, "fx").length) {
            hooks.empty.fire();
          }
        });
      });
    }
    if (elem.nodeType === 1 && ("height" in props || "width" in props)) {
      opts.overflow = [style.overflow, style.overflowX, style.overflowY];
      display = jQuery.css(elem, "display");
      checkDisplay = display === "none" ? data_priv.get(elem, "olddisplay") || defaultDisplay(elem.nodeName) : display;
      if (checkDisplay === "inline" && jQuery.css(elem, "float") === "none") {
        style.display = "inline-block";
      }
    }
    if (opts.overflow) {
      style.overflow = "hidden";
      anim.always(function() {
        style.overflow = opts.overflow[0];
        style.overflowX = opts.overflow[1];
        style.overflowY = opts.overflow[2];
      });
    }
    for (prop in props) {
      value = props[prop];
      if (rfxtypes.exec(value)) {
        delete props[prop];
        toggle = toggle || value === "toggle";
        if (value === (hidden ? "hide" : "show")) {
          if (value === "show" && dataShow && dataShow[prop] !== undefined) {
            hidden = true;
          } else {
            continue;
          }
        }
        orig[prop] = dataShow && dataShow[prop] || jQuery.style(elem, prop);
      } else {
        display = undefined;
      }
    }
    if (!jQuery.isEmptyObject(orig)) {
      if (dataShow) {
        if ("hidden" in dataShow) {
          hidden = dataShow.hidden;
        }
      } else {
        dataShow = data_priv.access(elem, "fxshow", {});
      }
      if (toggle) {
        dataShow.hidden = !hidden;
      }
      if (hidden) {
        jQuery(elem).show();
      } else {
        anim.done(function() {
          jQuery(elem).hide();
        });
      }
      anim.done(function() {
        var prop;
        data_priv.remove(elem, "fxshow");
        for (prop in orig) {
          jQuery.style(elem, prop, orig[prop]);
        }
      });
      for (prop in orig) {
        tween = createTween(hidden ? dataShow[prop] : 0, prop, anim);
        if (!(prop in dataShow)) {
          dataShow[prop] = tween.start;
          if (hidden) {
            tween.end = tween.start;
            tween.start = prop === "width" || prop === "height" ? 1 : 0;
          }
        }
      }
    } else if ((display === "none" ? defaultDisplay(elem.nodeName) : display) === "inline") {
      style.display = display;
    }
  }
  function propFilter(props, specialEasing) {
    var index,
        name,
        easing,
        value,
        hooks;
    for (index in props) {
      name = jQuery.camelCase(index);
      easing = specialEasing[name];
      value = props[index];
      if (jQuery.isArray(value)) {
        easing = value[1];
        value = props[index] = value[0];
      }
      if (index !== name) {
        props[name] = value;
        delete props[index];
      }
      hooks = jQuery.cssHooks[name];
      if (hooks && "expand" in hooks) {
        value = hooks.expand(value);
        delete props[name];
        for (index in value) {
          if (!(index in props)) {
            props[index] = value[index];
            specialEasing[index] = easing;
          }
        }
      } else {
        specialEasing[name] = easing;
      }
    }
  }
  function Animation(elem, properties, options) {
    var result,
        stopped,
        index = 0,
        length = animationPrefilters.length,
        deferred = jQuery.Deferred().always(function() {
          delete tick.elem;
        }),
        tick = function() {
          if (stopped) {
            return false;
          }
          var currentTime = fxNow || createFxNow(),
              remaining = Math.max(0, animation.startTime + animation.duration - currentTime),
              temp = remaining / animation.duration || 0,
              percent = 1 - temp,
              index = 0,
              length = animation.tweens.length;
          for (; index < length; index++) {
            animation.tweens[index].run(percent);
          }
          deferred.notifyWith(elem, [animation, percent, remaining]);
          if (percent < 1 && length) {
            return remaining;
          } else {
            deferred.resolveWith(elem, [animation]);
            return false;
          }
        },
        animation = deferred.promise({
          elem: elem,
          props: jQuery.extend({}, properties),
          opts: jQuery.extend(true, {specialEasing: {}}, options),
          originalProperties: properties,
          originalOptions: options,
          startTime: fxNow || createFxNow(),
          duration: options.duration,
          tweens: [],
          createTween: function(prop, end) {
            var tween = jQuery.Tween(elem, animation.opts, prop, end, animation.opts.specialEasing[prop] || animation.opts.easing);
            animation.tweens.push(tween);
            return tween;
          },
          stop: function(gotoEnd) {
            var index = 0,
                length = gotoEnd ? animation.tweens.length : 0;
            if (stopped) {
              return this;
            }
            stopped = true;
            for (; index < length; index++) {
              animation.tweens[index].run(1);
            }
            if (gotoEnd) {
              deferred.resolveWith(elem, [animation, gotoEnd]);
            } else {
              deferred.rejectWith(elem, [animation, gotoEnd]);
            }
            return this;
          }
        }),
        props = animation.props;
    propFilter(props, animation.opts.specialEasing);
    for (; index < length; index++) {
      result = animationPrefilters[index].call(animation, elem, props, animation.opts);
      if (result) {
        return result;
      }
    }
    jQuery.map(props, createTween, animation);
    if (jQuery.isFunction(animation.opts.start)) {
      animation.opts.start.call(elem, animation);
    }
    jQuery.fx.timer(jQuery.extend(tick, {
      elem: elem,
      anim: animation,
      queue: animation.opts.queue
    }));
    return animation.progress(animation.opts.progress).done(animation.opts.done, animation.opts.complete).fail(animation.opts.fail).always(animation.opts.always);
  }
  jQuery.Animation = jQuery.extend(Animation, {
    tweener: function(props, callback) {
      if (jQuery.isFunction(props)) {
        callback = props;
        props = ["*"];
      } else {
        props = props.split(" ");
      }
      var prop,
          index = 0,
          length = props.length;
      for (; index < length; index++) {
        prop = props[index];
        tweeners[prop] = tweeners[prop] || [];
        tweeners[prop].unshift(callback);
      }
    },
    prefilter: function(callback, prepend) {
      if (prepend) {
        animationPrefilters.unshift(callback);
      } else {
        animationPrefilters.push(callback);
      }
    }
  });
  jQuery.speed = function(speed, easing, fn) {
    var opt = speed && typeof speed === "object" ? jQuery.extend({}, speed) : {
      complete: fn || !fn && easing || jQuery.isFunction(speed) && speed,
      duration: speed,
      easing: fn && easing || easing && !jQuery.isFunction(easing) && easing
    };
    opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration : opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[opt.duration] : jQuery.fx.speeds._default;
    if (opt.queue == null || opt.queue === true) {
      opt.queue = "fx";
    }
    opt.old = opt.complete;
    opt.complete = function() {
      if (jQuery.isFunction(opt.old)) {
        opt.old.call(this);
      }
      if (opt.queue) {
        jQuery.dequeue(this, opt.queue);
      }
    };
    return opt;
  };
  jQuery.fn.extend({
    fadeTo: function(speed, to, easing, callback) {
      return this.filter(isHidden).css("opacity", 0).show().end().animate({opacity: to}, speed, easing, callback);
    },
    animate: function(prop, speed, easing, callback) {
      var empty = jQuery.isEmptyObject(prop),
          optall = jQuery.speed(speed, easing, callback),
          doAnimation = function() {
            var anim = Animation(this, jQuery.extend({}, prop), optall);
            if (empty || data_priv.get(this, "finish")) {
              anim.stop(true);
            }
          };
      doAnimation.finish = doAnimation;
      return empty || optall.queue === false ? this.each(doAnimation) : this.queue(optall.queue, doAnimation);
    },
    stop: function(type, clearQueue, gotoEnd) {
      var stopQueue = function(hooks) {
        var stop = hooks.stop;
        delete hooks.stop;
        stop(gotoEnd);
      };
      if (typeof type !== "string") {
        gotoEnd = clearQueue;
        clearQueue = type;
        type = undefined;
      }
      if (clearQueue && type !== false) {
        this.queue(type || "fx", []);
      }
      return this.each(function() {
        var dequeue = true,
            index = type != null && type + "queueHooks",
            timers = jQuery.timers,
            data = data_priv.get(this);
        if (index) {
          if (data[index] && data[index].stop) {
            stopQueue(data[index]);
          }
        } else {
          for (index in data) {
            if (data[index] && data[index].stop && rrun.test(index)) {
              stopQueue(data[index]);
            }
          }
        }
        for (index = timers.length; index--; ) {
          if (timers[index].elem === this && (type == null || timers[index].queue === type)) {
            timers[index].anim.stop(gotoEnd);
            dequeue = false;
            timers.splice(index, 1);
          }
        }
        if (dequeue || !gotoEnd) {
          jQuery.dequeue(this, type);
        }
      });
    },
    finish: function(type) {
      if (type !== false) {
        type = type || "fx";
      }
      return this.each(function() {
        var index,
            data = data_priv.get(this),
            queue = data[type + "queue"],
            hooks = data[type + "queueHooks"],
            timers = jQuery.timers,
            length = queue ? queue.length : 0;
        data.finish = true;
        jQuery.queue(this, type, []);
        if (hooks && hooks.stop) {
          hooks.stop.call(this, true);
        }
        for (index = timers.length; index--; ) {
          if (timers[index].elem === this && timers[index].queue === type) {
            timers[index].anim.stop(true);
            timers.splice(index, 1);
          }
        }
        for (index = 0; index < length; index++) {
          if (queue[index] && queue[index].finish) {
            queue[index].finish.call(this);
          }
        }
        delete data.finish;
      });
    }
  });
  jQuery.each(["toggle", "show", "hide"], function(i, name) {
    var cssFn = jQuery.fn[name];
    jQuery.fn[name] = function(speed, easing, callback) {
      return speed == null || typeof speed === "boolean" ? cssFn.apply(this, arguments) : this.animate(genFx(name, true), speed, easing, callback);
    };
  });
  jQuery.each({
    slideDown: genFx("show"),
    slideUp: genFx("hide"),
    slideToggle: genFx("toggle"),
    fadeIn: {opacity: "show"},
    fadeOut: {opacity: "hide"},
    fadeToggle: {opacity: "toggle"}
  }, function(name, props) {
    jQuery.fn[name] = function(speed, easing, callback) {
      return this.animate(props, speed, easing, callback);
    };
  });
  jQuery.timers = [];
  jQuery.fx.tick = function() {
    var timer,
        i = 0,
        timers = jQuery.timers;
    fxNow = jQuery.now();
    for (; i < timers.length; i++) {
      timer = timers[i];
      if (!timer() && timers[i] === timer) {
        timers.splice(i--, 1);
      }
    }
    if (!timers.length) {
      jQuery.fx.stop();
    }
    fxNow = undefined;
  };
  jQuery.fx.timer = function(timer) {
    jQuery.timers.push(timer);
    if (timer()) {
      jQuery.fx.start();
    } else {
      jQuery.timers.pop();
    }
  };
  jQuery.fx.interval = 13;
  jQuery.fx.start = function() {
    if (!timerId) {
      timerId = setInterval(jQuery.fx.tick, jQuery.fx.interval);
    }
  };
  jQuery.fx.stop = function() {
    clearInterval(timerId);
    timerId = null;
  };
  jQuery.fx.speeds = {
    slow: 600,
    fast: 200,
    _default: 400
  };
  jQuery.fn.delay = function(time, type) {
    time = jQuery.fx ? jQuery.fx.speeds[time] || time : time;
    type = type || "fx";
    return this.queue(type, function(next, hooks) {
      var timeout = setTimeout(next, time);
      hooks.stop = function() {
        clearTimeout(timeout);
      };
    });
  };
  (function() {
    var input = document.createElement("input"),
        select = document.createElement("select"),
        opt = select.appendChild(document.createElement("option"));
    input.type = "checkbox";
    support.checkOn = input.value !== "";
    support.optSelected = opt.selected;
    select.disabled = true;
    support.optDisabled = !opt.disabled;
    input = document.createElement("input");
    input.value = "t";
    input.type = "radio";
    support.radioValue = input.value === "t";
  })();
  var nodeHook,
      boolHook,
      attrHandle = jQuery.expr.attrHandle;
  jQuery.fn.extend({
    attr: function(name, value) {
      return access(this, jQuery.attr, name, value, arguments.length > 1);
    },
    removeAttr: function(name) {
      return this.each(function() {
        jQuery.removeAttr(this, name);
      });
    }
  });
  jQuery.extend({
    attr: function(elem, name, value) {
      var hooks,
          ret,
          nType = elem.nodeType;
      if (!elem || nType === 3 || nType === 8 || nType === 2) {
        return;
      }
      if (typeof elem.getAttribute === strundefined) {
        return jQuery.prop(elem, name, value);
      }
      if (nType !== 1 || !jQuery.isXMLDoc(elem)) {
        name = name.toLowerCase();
        hooks = jQuery.attrHooks[name] || (jQuery.expr.match.bool.test(name) ? boolHook : nodeHook);
      }
      if (value !== undefined) {
        if (value === null) {
          jQuery.removeAttr(elem, name);
        } else if (hooks && "set" in hooks && (ret = hooks.set(elem, value, name)) !== undefined) {
          return ret;
        } else {
          elem.setAttribute(name, value + "");
          return value;
        }
      } else if (hooks && "get" in hooks && (ret = hooks.get(elem, name)) !== null) {
        return ret;
      } else {
        ret = jQuery.find.attr(elem, name);
        return ret == null ? undefined : ret;
      }
    },
    removeAttr: function(elem, value) {
      var name,
          propName,
          i = 0,
          attrNames = value && value.match(rnotwhite);
      if (attrNames && elem.nodeType === 1) {
        while ((name = attrNames[i++])) {
          propName = jQuery.propFix[name] || name;
          if (jQuery.expr.match.bool.test(name)) {
            elem[propName] = false;
          }
          elem.removeAttribute(name);
        }
      }
    },
    attrHooks: {type: {set: function(elem, value) {
          if (!support.radioValue && value === "radio" && jQuery.nodeName(elem, "input")) {
            var val = elem.value;
            elem.setAttribute("type", value);
            if (val) {
              elem.value = val;
            }
            return value;
          }
        }}}
  });
  boolHook = {set: function(elem, value, name) {
      if (value === false) {
        jQuery.removeAttr(elem, name);
      } else {
        elem.setAttribute(name, name);
      }
      return name;
    }};
  jQuery.each(jQuery.expr.match.bool.source.match(/\w+/g), function(i, name) {
    var getter = attrHandle[name] || jQuery.find.attr;
    attrHandle[name] = function(elem, name, isXML) {
      var ret,
          handle;
      if (!isXML) {
        handle = attrHandle[name];
        attrHandle[name] = ret;
        ret = getter(elem, name, isXML) != null ? name.toLowerCase() : null;
        attrHandle[name] = handle;
      }
      return ret;
    };
  });
  var rfocusable = /^(?:input|select|textarea|button)$/i;
  jQuery.fn.extend({
    prop: function(name, value) {
      return access(this, jQuery.prop, name, value, arguments.length > 1);
    },
    removeProp: function(name) {
      return this.each(function() {
        delete this[jQuery.propFix[name] || name];
      });
    }
  });
  jQuery.extend({
    propFix: {
      "for": "htmlFor",
      "class": "className"
    },
    prop: function(elem, name, value) {
      var ret,
          hooks,
          notxml,
          nType = elem.nodeType;
      if (!elem || nType === 3 || nType === 8 || nType === 2) {
        return;
      }
      notxml = nType !== 1 || !jQuery.isXMLDoc(elem);
      if (notxml) {
        name = jQuery.propFix[name] || name;
        hooks = jQuery.propHooks[name];
      }
      if (value !== undefined) {
        return hooks && "set" in hooks && (ret = hooks.set(elem, value, name)) !== undefined ? ret : (elem[name] = value);
      } else {
        return hooks && "get" in hooks && (ret = hooks.get(elem, name)) !== null ? ret : elem[name];
      }
    },
    propHooks: {tabIndex: {get: function(elem) {
          return elem.hasAttribute("tabindex") || rfocusable.test(elem.nodeName) || elem.href ? elem.tabIndex : -1;
        }}}
  });
  if (!support.optSelected) {
    jQuery.propHooks.selected = {get: function(elem) {
        var parent = elem.parentNode;
        if (parent && parent.parentNode) {
          parent.parentNode.selectedIndex;
        }
        return null;
      }};
  }
  jQuery.each(["tabIndex", "readOnly", "maxLength", "cellSpacing", "cellPadding", "rowSpan", "colSpan", "useMap", "frameBorder", "contentEditable"], function() {
    jQuery.propFix[this.toLowerCase()] = this;
  });
  var rclass = /[\t\r\n\f]/g;
  jQuery.fn.extend({
    addClass: function(value) {
      var classes,
          elem,
          cur,
          clazz,
          j,
          finalValue,
          proceed = typeof value === "string" && value,
          i = 0,
          len = this.length;
      if (jQuery.isFunction(value)) {
        return this.each(function(j) {
          jQuery(this).addClass(value.call(this, j, this.className));
        });
      }
      if (proceed) {
        classes = (value || "").match(rnotwhite) || [];
        for (; i < len; i++) {
          elem = this[i];
          cur = elem.nodeType === 1 && (elem.className ? (" " + elem.className + " ").replace(rclass, " ") : " ");
          if (cur) {
            j = 0;
            while ((clazz = classes[j++])) {
              if (cur.indexOf(" " + clazz + " ") < 0) {
                cur += clazz + " ";
              }
            }
            finalValue = jQuery.trim(cur);
            if (elem.className !== finalValue) {
              elem.className = finalValue;
            }
          }
        }
      }
      return this;
    },
    removeClass: function(value) {
      var classes,
          elem,
          cur,
          clazz,
          j,
          finalValue,
          proceed = arguments.length === 0 || typeof value === "string" && value,
          i = 0,
          len = this.length;
      if (jQuery.isFunction(value)) {
        return this.each(function(j) {
          jQuery(this).removeClass(value.call(this, j, this.className));
        });
      }
      if (proceed) {
        classes = (value || "").match(rnotwhite) || [];
        for (; i < len; i++) {
          elem = this[i];
          cur = elem.nodeType === 1 && (elem.className ? (" " + elem.className + " ").replace(rclass, " ") : "");
          if (cur) {
            j = 0;
            while ((clazz = classes[j++])) {
              while (cur.indexOf(" " + clazz + " ") >= 0) {
                cur = cur.replace(" " + clazz + " ", " ");
              }
            }
            finalValue = value ? jQuery.trim(cur) : "";
            if (elem.className !== finalValue) {
              elem.className = finalValue;
            }
          }
        }
      }
      return this;
    },
    toggleClass: function(value, stateVal) {
      var type = typeof value;
      if (typeof stateVal === "boolean" && type === "string") {
        return stateVal ? this.addClass(value) : this.removeClass(value);
      }
      if (jQuery.isFunction(value)) {
        return this.each(function(i) {
          jQuery(this).toggleClass(value.call(this, i, this.className, stateVal), stateVal);
        });
      }
      return this.each(function() {
        if (type === "string") {
          var className,
              i = 0,
              self = jQuery(this),
              classNames = value.match(rnotwhite) || [];
          while ((className = classNames[i++])) {
            if (self.hasClass(className)) {
              self.removeClass(className);
            } else {
              self.addClass(className);
            }
          }
        } else if (type === strundefined || type === "boolean") {
          if (this.className) {
            data_priv.set(this, "__className__", this.className);
          }
          this.className = this.className || value === false ? "" : data_priv.get(this, "__className__") || "";
        }
      });
    },
    hasClass: function(selector) {
      var className = " " + selector + " ",
          i = 0,
          l = this.length;
      for (; i < l; i++) {
        if (this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf(className) >= 0) {
          return true;
        }
      }
      return false;
    }
  });
  var rreturn = /\r/g;
  jQuery.fn.extend({val: function(value) {
      var hooks,
          ret,
          isFunction,
          elem = this[0];
      if (!arguments.length) {
        if (elem) {
          hooks = jQuery.valHooks[elem.type] || jQuery.valHooks[elem.nodeName.toLowerCase()];
          if (hooks && "get" in hooks && (ret = hooks.get(elem, "value")) !== undefined) {
            return ret;
          }
          ret = elem.value;
          return typeof ret === "string" ? ret.replace(rreturn, "") : ret == null ? "" : ret;
        }
        return;
      }
      isFunction = jQuery.isFunction(value);
      return this.each(function(i) {
        var val;
        if (this.nodeType !== 1) {
          return;
        }
        if (isFunction) {
          val = value.call(this, i, jQuery(this).val());
        } else {
          val = value;
        }
        if (val == null) {
          val = "";
        } else if (typeof val === "number") {
          val += "";
        } else if (jQuery.isArray(val)) {
          val = jQuery.map(val, function(value) {
            return value == null ? "" : value + "";
          });
        }
        hooks = jQuery.valHooks[this.type] || jQuery.valHooks[this.nodeName.toLowerCase()];
        if (!hooks || !("set" in hooks) || hooks.set(this, val, "value") === undefined) {
          this.value = val;
        }
      });
    }});
  jQuery.extend({valHooks: {
      option: {get: function(elem) {
          var val = jQuery.find.attr(elem, "value");
          return val != null ? val : jQuery.trim(jQuery.text(elem));
        }},
      select: {
        get: function(elem) {
          var value,
              option,
              options = elem.options,
              index = elem.selectedIndex,
              one = elem.type === "select-one" || index < 0,
              values = one ? null : [],
              max = one ? index + 1 : options.length,
              i = index < 0 ? max : one ? index : 0;
          for (; i < max; i++) {
            option = options[i];
            if ((option.selected || i === index) && (support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && (!option.parentNode.disabled || !jQuery.nodeName(option.parentNode, "optgroup"))) {
              value = jQuery(option).val();
              if (one) {
                return value;
              }
              values.push(value);
            }
          }
          return values;
        },
        set: function(elem, value) {
          var optionSet,
              option,
              options = elem.options,
              values = jQuery.makeArray(value),
              i = options.length;
          while (i--) {
            option = options[i];
            if ((option.selected = jQuery.inArray(option.value, values) >= 0)) {
              optionSet = true;
            }
          }
          if (!optionSet) {
            elem.selectedIndex = -1;
          }
          return values;
        }
      }
    }});
  jQuery.each(["radio", "checkbox"], function() {
    jQuery.valHooks[this] = {set: function(elem, value) {
        if (jQuery.isArray(value)) {
          return (elem.checked = jQuery.inArray(jQuery(elem).val(), value) >= 0);
        }
      }};
    if (!support.checkOn) {
      jQuery.valHooks[this].get = function(elem) {
        return elem.getAttribute("value") === null ? "on" : elem.value;
      };
    }
  });
  jQuery.each(("blur focus focusin focusout load resize scroll unload click dblclick " + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + "change select submit keydown keypress keyup error contextmenu").split(" "), function(i, name) {
    jQuery.fn[name] = function(data, fn) {
      return arguments.length > 0 ? this.on(name, null, data, fn) : this.trigger(name);
    };
  });
  jQuery.fn.extend({
    hover: function(fnOver, fnOut) {
      return this.mouseenter(fnOver).mouseleave(fnOut || fnOver);
    },
    bind: function(types, data, fn) {
      return this.on(types, null, data, fn);
    },
    unbind: function(types, fn) {
      return this.off(types, null, fn);
    },
    delegate: function(selector, types, data, fn) {
      return this.on(types, selector, data, fn);
    },
    undelegate: function(selector, types, fn) {
      return arguments.length === 1 ? this.off(selector, "**") : this.off(types, selector || "**", fn);
    }
  });
  var nonce = jQuery.now();
  var rquery = (/\?/);
  jQuery.parseJSON = function(data) {
    return JSON.parse(data + "");
  };
  jQuery.parseXML = function(data) {
    var xml,
        tmp;
    if (!data || typeof data !== "string") {
      return null;
    }
    try {
      tmp = new DOMParser();
      xml = tmp.parseFromString(data, "text/xml");
    } catch (e) {
      xml = undefined;
    }
    if (!xml || xml.getElementsByTagName("parsererror").length) {
      jQuery.error("Invalid XML: " + data);
    }
    return xml;
  };
  var rhash = /#.*$/,
      rts = /([?&])_=[^&]*/,
      rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg,
      rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
      rnoContent = /^(?:GET|HEAD)$/,
      rprotocol = /^\/\//,
      rurl = /^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,
      prefilters = {},
      transports = {},
      allTypes = "*/".concat("*"),
      ajaxLocation = window.location.href,
      ajaxLocParts = rurl.exec(ajaxLocation.toLowerCase()) || [];
  function addToPrefiltersOrTransports(structure) {
    return function(dataTypeExpression, func) {
      if (typeof dataTypeExpression !== "string") {
        func = dataTypeExpression;
        dataTypeExpression = "*";
      }
      var dataType,
          i = 0,
          dataTypes = dataTypeExpression.toLowerCase().match(rnotwhite) || [];
      if (jQuery.isFunction(func)) {
        while ((dataType = dataTypes[i++])) {
          if (dataType[0] === "+") {
            dataType = dataType.slice(1) || "*";
            (structure[dataType] = structure[dataType] || []).unshift(func);
          } else {
            (structure[dataType] = structure[dataType] || []).push(func);
          }
        }
      }
    };
  }
  function inspectPrefiltersOrTransports(structure, options, originalOptions, jqXHR) {
    var inspected = {},
        seekingTransport = (structure === transports);
    function inspect(dataType) {
      var selected;
      inspected[dataType] = true;
      jQuery.each(structure[dataType] || [], function(_, prefilterOrFactory) {
        var dataTypeOrTransport = prefilterOrFactory(options, originalOptions, jqXHR);
        if (typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[dataTypeOrTransport]) {
          options.dataTypes.unshift(dataTypeOrTransport);
          inspect(dataTypeOrTransport);
          return false;
        } else if (seekingTransport) {
          return !(selected = dataTypeOrTransport);
        }
      });
      return selected;
    }
    return inspect(options.dataTypes[0]) || !inspected["*"] && inspect("*");
  }
  function ajaxExtend(target, src) {
    var key,
        deep,
        flatOptions = jQuery.ajaxSettings.flatOptions || {};
    for (key in src) {
      if (src[key] !== undefined) {
        (flatOptions[key] ? target : (deep || (deep = {})))[key] = src[key];
      }
    }
    if (deep) {
      jQuery.extend(true, target, deep);
    }
    return target;
  }
  function ajaxHandleResponses(s, jqXHR, responses) {
    var ct,
        type,
        finalDataType,
        firstDataType,
        contents = s.contents,
        dataTypes = s.dataTypes;
    while (dataTypes[0] === "*") {
      dataTypes.shift();
      if (ct === undefined) {
        ct = s.mimeType || jqXHR.getResponseHeader("Content-Type");
      }
    }
    if (ct) {
      for (type in contents) {
        if (contents[type] && contents[type].test(ct)) {
          dataTypes.unshift(type);
          break;
        }
      }
    }
    if (dataTypes[0] in responses) {
      finalDataType = dataTypes[0];
    } else {
      for (type in responses) {
        if (!dataTypes[0] || s.converters[type + " " + dataTypes[0]]) {
          finalDataType = type;
          break;
        }
        if (!firstDataType) {
          firstDataType = type;
        }
      }
      finalDataType = finalDataType || firstDataType;
    }
    if (finalDataType) {
      if (finalDataType !== dataTypes[0]) {
        dataTypes.unshift(finalDataType);
      }
      return responses[finalDataType];
    }
  }
  function ajaxConvert(s, response, jqXHR, isSuccess) {
    var conv2,
        current,
        conv,
        tmp,
        prev,
        converters = {},
        dataTypes = s.dataTypes.slice();
    if (dataTypes[1]) {
      for (conv in s.converters) {
        converters[conv.toLowerCase()] = s.converters[conv];
      }
    }
    current = dataTypes.shift();
    while (current) {
      if (s.responseFields[current]) {
        jqXHR[s.responseFields[current]] = response;
      }
      if (!prev && isSuccess && s.dataFilter) {
        response = s.dataFilter(response, s.dataType);
      }
      prev = current;
      current = dataTypes.shift();
      if (current) {
        if (current === "*") {
          current = prev;
        } else if (prev !== "*" && prev !== current) {
          conv = converters[prev + " " + current] || converters["* " + current];
          if (!conv) {
            for (conv2 in converters) {
              tmp = conv2.split(" ");
              if (tmp[1] === current) {
                conv = converters[prev + " " + tmp[0]] || converters["* " + tmp[0]];
                if (conv) {
                  if (conv === true) {
                    conv = converters[conv2];
                  } else if (converters[conv2] !== true) {
                    current = tmp[0];
                    dataTypes.unshift(tmp[1]);
                  }
                  break;
                }
              }
            }
          }
          if (conv !== true) {
            if (conv && s["throws"]) {
              response = conv(response);
            } else {
              try {
                response = conv(response);
              } catch (e) {
                return {
                  state: "parsererror",
                  error: conv ? e : "No conversion from " + prev + " to " + current
                };
              }
            }
          }
        }
      }
    }
    return {
      state: "success",
      data: response
    };
  }
  jQuery.extend({
    active: 0,
    lastModified: {},
    etag: {},
    ajaxSettings: {
      url: ajaxLocation,
      type: "GET",
      isLocal: rlocalProtocol.test(ajaxLocParts[1]),
      global: true,
      processData: true,
      async: true,
      contentType: "application/x-www-form-urlencoded; charset=UTF-8",
      accepts: {
        "*": allTypes,
        text: "text/plain",
        html: "text/html",
        xml: "application/xml, text/xml",
        json: "application/json, text/javascript"
      },
      contents: {
        xml: /xml/,
        html: /html/,
        json: /json/
      },
      responseFields: {
        xml: "responseXML",
        text: "responseText",
        json: "responseJSON"
      },
      converters: {
        "* text": String,
        "text html": true,
        "text json": jQuery.parseJSON,
        "text xml": jQuery.parseXML
      },
      flatOptions: {
        url: true,
        context: true
      }
    },
    ajaxSetup: function(target, settings) {
      return settings ? ajaxExtend(ajaxExtend(target, jQuery.ajaxSettings), settings) : ajaxExtend(jQuery.ajaxSettings, target);
    },
    ajaxPrefilter: addToPrefiltersOrTransports(prefilters),
    ajaxTransport: addToPrefiltersOrTransports(transports),
    ajax: function(url, options) {
      if (typeof url === "object") {
        options = url;
        url = undefined;
      }
      options = options || {};
      var transport,
          cacheURL,
          responseHeadersString,
          responseHeaders,
          timeoutTimer,
          parts,
          fireGlobals,
          i,
          s = jQuery.ajaxSetup({}, options),
          callbackContext = s.context || s,
          globalEventContext = s.context && (callbackContext.nodeType || callbackContext.jquery) ? jQuery(callbackContext) : jQuery.event,
          deferred = jQuery.Deferred(),
          completeDeferred = jQuery.Callbacks("once memory"),
          statusCode = s.statusCode || {},
          requestHeaders = {},
          requestHeadersNames = {},
          state = 0,
          strAbort = "canceled",
          jqXHR = {
            readyState: 0,
            getResponseHeader: function(key) {
              var match;
              if (state === 2) {
                if (!responseHeaders) {
                  responseHeaders = {};
                  while ((match = rheaders.exec(responseHeadersString))) {
                    responseHeaders[match[1].toLowerCase()] = match[2];
                  }
                }
                match = responseHeaders[key.toLowerCase()];
              }
              return match == null ? null : match;
            },
            getAllResponseHeaders: function() {
              return state === 2 ? responseHeadersString : null;
            },
            setRequestHeader: function(name, value) {
              var lname = name.toLowerCase();
              if (!state) {
                name = requestHeadersNames[lname] = requestHeadersNames[lname] || name;
                requestHeaders[name] = value;
              }
              return this;
            },
            overrideMimeType: function(type) {
              if (!state) {
                s.mimeType = type;
              }
              return this;
            },
            statusCode: function(map) {
              var code;
              if (map) {
                if (state < 2) {
                  for (code in map) {
                    statusCode[code] = [statusCode[code], map[code]];
                  }
                } else {
                  jqXHR.always(map[jqXHR.status]);
                }
              }
              return this;
            },
            abort: function(statusText) {
              var finalText = statusText || strAbort;
              if (transport) {
                transport.abort(finalText);
              }
              done(0, finalText);
              return this;
            }
          };
      deferred.promise(jqXHR).complete = completeDeferred.add;
      jqXHR.success = jqXHR.done;
      jqXHR.error = jqXHR.fail;
      s.url = ((url || s.url || ajaxLocation) + "").replace(rhash, "").replace(rprotocol, ajaxLocParts[1] + "//");
      s.type = options.method || options.type || s.method || s.type;
      s.dataTypes = jQuery.trim(s.dataType || "*").toLowerCase().match(rnotwhite) || [""];
      if (s.crossDomain == null) {
        parts = rurl.exec(s.url.toLowerCase());
        s.crossDomain = !!(parts && (parts[1] !== ajaxLocParts[1] || parts[2] !== ajaxLocParts[2] || (parts[3] || (parts[1] === "http:" ? "80" : "443")) !== (ajaxLocParts[3] || (ajaxLocParts[1] === "http:" ? "80" : "443"))));
      }
      if (s.data && s.processData && typeof s.data !== "string") {
        s.data = jQuery.param(s.data, s.traditional);
      }
      inspectPrefiltersOrTransports(prefilters, s, options, jqXHR);
      if (state === 2) {
        return jqXHR;
      }
      fireGlobals = jQuery.event && s.global;
      if (fireGlobals && jQuery.active++ === 0) {
        jQuery.event.trigger("ajaxStart");
      }
      s.type = s.type.toUpperCase();
      s.hasContent = !rnoContent.test(s.type);
      cacheURL = s.url;
      if (!s.hasContent) {
        if (s.data) {
          cacheURL = (s.url += (rquery.test(cacheURL) ? "&" : "?") + s.data);
          delete s.data;
        }
        if (s.cache === false) {
          s.url = rts.test(cacheURL) ? cacheURL.replace(rts, "$1_=" + nonce++) : cacheURL + (rquery.test(cacheURL) ? "&" : "?") + "_=" + nonce++;
        }
      }
      if (s.ifModified) {
        if (jQuery.lastModified[cacheURL]) {
          jqXHR.setRequestHeader("If-Modified-Since", jQuery.lastModified[cacheURL]);
        }
        if (jQuery.etag[cacheURL]) {
          jqXHR.setRequestHeader("If-None-Match", jQuery.etag[cacheURL]);
        }
      }
      if (s.data && s.hasContent && s.contentType !== false || options.contentType) {
        jqXHR.setRequestHeader("Content-Type", s.contentType);
      }
      jqXHR.setRequestHeader("Accept", s.dataTypes[0] && s.accepts[s.dataTypes[0]] ? s.accepts[s.dataTypes[0]] + (s.dataTypes[0] !== "*" ? ", " + allTypes + "; q=0.01" : "") : s.accepts["*"]);
      for (i in s.headers) {
        jqXHR.setRequestHeader(i, s.headers[i]);
      }
      if (s.beforeSend && (s.beforeSend.call(callbackContext, jqXHR, s) === false || state === 2)) {
        return jqXHR.abort();
      }
      strAbort = "abort";
      for (i in {
        success: 1,
        error: 1,
        complete: 1
      }) {
        jqXHR[i](s[i]);
      }
      transport = inspectPrefiltersOrTransports(transports, s, options, jqXHR);
      if (!transport) {
        done(-1, "No Transport");
      } else {
        jqXHR.readyState = 1;
        if (fireGlobals) {
          globalEventContext.trigger("ajaxSend", [jqXHR, s]);
        }
        if (s.async && s.timeout > 0) {
          timeoutTimer = setTimeout(function() {
            jqXHR.abort("timeout");
          }, s.timeout);
        }
        try {
          state = 1;
          transport.send(requestHeaders, done);
        } catch (e) {
          if (state < 2) {
            done(-1, e);
          } else {
            throw e;
          }
        }
      }
      function done(status, nativeStatusText, responses, headers) {
        var isSuccess,
            success,
            error,
            response,
            modified,
            statusText = nativeStatusText;
        if (state === 2) {
          return;
        }
        state = 2;
        if (timeoutTimer) {
          clearTimeout(timeoutTimer);
        }
        transport = undefined;
        responseHeadersString = headers || "";
        jqXHR.readyState = status > 0 ? 4 : 0;
        isSuccess = status >= 200 && status < 300 || status === 304;
        if (responses) {
          response = ajaxHandleResponses(s, jqXHR, responses);
        }
        response = ajaxConvert(s, response, jqXHR, isSuccess);
        if (isSuccess) {
          if (s.ifModified) {
            modified = jqXHR.getResponseHeader("Last-Modified");
            if (modified) {
              jQuery.lastModified[cacheURL] = modified;
            }
            modified = jqXHR.getResponseHeader("etag");
            if (modified) {
              jQuery.etag[cacheURL] = modified;
            }
          }
          if (status === 204 || s.type === "HEAD") {
            statusText = "nocontent";
          } else if (status === 304) {
            statusText = "notmodified";
          } else {
            statusText = response.state;
            success = response.data;
            error = response.error;
            isSuccess = !error;
          }
        } else {
          error = statusText;
          if (status || !statusText) {
            statusText = "error";
            if (status < 0) {
              status = 0;
            }
          }
        }
        jqXHR.status = status;
        jqXHR.statusText = (nativeStatusText || statusText) + "";
        if (isSuccess) {
          deferred.resolveWith(callbackContext, [success, statusText, jqXHR]);
        } else {
          deferred.rejectWith(callbackContext, [jqXHR, statusText, error]);
        }
        jqXHR.statusCode(statusCode);
        statusCode = undefined;
        if (fireGlobals) {
          globalEventContext.trigger(isSuccess ? "ajaxSuccess" : "ajaxError", [jqXHR, s, isSuccess ? success : error]);
        }
        completeDeferred.fireWith(callbackContext, [jqXHR, statusText]);
        if (fireGlobals) {
          globalEventContext.trigger("ajaxComplete", [jqXHR, s]);
          if (!(--jQuery.active)) {
            jQuery.event.trigger("ajaxStop");
          }
        }
      }
      return jqXHR;
    },
    getJSON: function(url, data, callback) {
      return jQuery.get(url, data, callback, "json");
    },
    getScript: function(url, callback) {
      return jQuery.get(url, undefined, callback, "script");
    }
  });
  jQuery.each(["get", "post"], function(i, method) {
    jQuery[method] = function(url, data, callback, type) {
      if (jQuery.isFunction(data)) {
        type = type || callback;
        callback = data;
        data = undefined;
      }
      return jQuery.ajax({
        url: url,
        type: method,
        dataType: type,
        data: data,
        success: callback
      });
    };
  });
  jQuery._evalUrl = function(url) {
    return jQuery.ajax({
      url: url,
      type: "GET",
      dataType: "script",
      async: false,
      global: false,
      "throws": true
    });
  };
  jQuery.fn.extend({
    wrapAll: function(html) {
      var wrap;
      if (jQuery.isFunction(html)) {
        return this.each(function(i) {
          jQuery(this).wrapAll(html.call(this, i));
        });
      }
      if (this[0]) {
        wrap = jQuery(html, this[0].ownerDocument).eq(0).clone(true);
        if (this[0].parentNode) {
          wrap.insertBefore(this[0]);
        }
        wrap.map(function() {
          var elem = this;
          while (elem.firstElementChild) {
            elem = elem.firstElementChild;
          }
          return elem;
        }).append(this);
      }
      return this;
    },
    wrapInner: function(html) {
      if (jQuery.isFunction(html)) {
        return this.each(function(i) {
          jQuery(this).wrapInner(html.call(this, i));
        });
      }
      return this.each(function() {
        var self = jQuery(this),
            contents = self.contents();
        if (contents.length) {
          contents.wrapAll(html);
        } else {
          self.append(html);
        }
      });
    },
    wrap: function(html) {
      var isFunction = jQuery.isFunction(html);
      return this.each(function(i) {
        jQuery(this).wrapAll(isFunction ? html.call(this, i) : html);
      });
    },
    unwrap: function() {
      return this.parent().each(function() {
        if (!jQuery.nodeName(this, "body")) {
          jQuery(this).replaceWith(this.childNodes);
        }
      }).end();
    }
  });
  jQuery.expr.filters.hidden = function(elem) {
    return elem.offsetWidth <= 0 && elem.offsetHeight <= 0;
  };
  jQuery.expr.filters.visible = function(elem) {
    return !jQuery.expr.filters.hidden(elem);
  };
  var r20 = /%20/g,
      rbracket = /\[\]$/,
      rCRLF = /\r?\n/g,
      rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
      rsubmittable = /^(?:input|select|textarea|keygen)/i;
  function buildParams(prefix, obj, traditional, add) {
    var name;
    if (jQuery.isArray(obj)) {
      jQuery.each(obj, function(i, v) {
        if (traditional || rbracket.test(prefix)) {
          add(prefix, v);
        } else {
          buildParams(prefix + "[" + (typeof v === "object" ? i : "") + "]", v, traditional, add);
        }
      });
    } else if (!traditional && jQuery.type(obj) === "object") {
      for (name in obj) {
        buildParams(prefix + "[" + name + "]", obj[name], traditional, add);
      }
    } else {
      add(prefix, obj);
    }
  }
  jQuery.param = function(a, traditional) {
    var prefix,
        s = [],
        add = function(key, value) {
          value = jQuery.isFunction(value) ? value() : (value == null ? "" : value);
          s[s.length] = encodeURIComponent(key) + "=" + encodeURIComponent(value);
        };
    if (traditional === undefined) {
      traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
    }
    if (jQuery.isArray(a) || (a.jquery && !jQuery.isPlainObject(a))) {
      jQuery.each(a, function() {
        add(this.name, this.value);
      });
    } else {
      for (prefix in a) {
        buildParams(prefix, a[prefix], traditional, add);
      }
    }
    return s.join("&").replace(r20, "+");
  };
  jQuery.fn.extend({
    serialize: function() {
      return jQuery.param(this.serializeArray());
    },
    serializeArray: function() {
      return this.map(function() {
        var elements = jQuery.prop(this, "elements");
        return elements ? jQuery.makeArray(elements) : this;
      }).filter(function() {
        var type = this.type;
        return this.name && !jQuery(this).is(":disabled") && rsubmittable.test(this.nodeName) && !rsubmitterTypes.test(type) && (this.checked || !rcheckableType.test(type));
      }).map(function(i, elem) {
        var val = jQuery(this).val();
        return val == null ? null : jQuery.isArray(val) ? jQuery.map(val, function(val) {
          return {
            name: elem.name,
            value: val.replace(rCRLF, "\r\n")
          };
        }) : {
          name: elem.name,
          value: val.replace(rCRLF, "\r\n")
        };
      }).get();
    }
  });
  jQuery.ajaxSettings.xhr = function() {
    try {
      return new XMLHttpRequest();
    } catch (e) {}
  };
  var xhrId = 0,
      xhrCallbacks = {},
      xhrSuccessStatus = {
        0: 200,
        1223: 204
      },
      xhrSupported = jQuery.ajaxSettings.xhr();
  if (window.attachEvent) {
    window.attachEvent("onunload", function() {
      for (var key in xhrCallbacks) {
        xhrCallbacks[key]();
      }
    });
  }
  support.cors = !!xhrSupported && ("withCredentials" in xhrSupported);
  support.ajax = xhrSupported = !!xhrSupported;
  jQuery.ajaxTransport(function(options) {
    var callback;
    if (support.cors || xhrSupported && !options.crossDomain) {
      return {
        send: function(headers, complete) {
          var i,
              xhr = options.xhr(),
              id = ++xhrId;
          xhr.open(options.type, options.url, options.async, options.username, options.password);
          if (options.xhrFields) {
            for (i in options.xhrFields) {
              xhr[i] = options.xhrFields[i];
            }
          }
          if (options.mimeType && xhr.overrideMimeType) {
            xhr.overrideMimeType(options.mimeType);
          }
          if (!options.crossDomain && !headers["X-Requested-With"]) {
            headers["X-Requested-With"] = "XMLHttpRequest";
          }
          for (i in headers) {
            xhr.setRequestHeader(i, headers[i]);
          }
          callback = function(type) {
            return function() {
              if (callback) {
                delete xhrCallbacks[id];
                callback = xhr.onload = xhr.onerror = null;
                if (type === "abort") {
                  xhr.abort();
                } else if (type === "error") {
                  complete(xhr.status, xhr.statusText);
                } else {
                  complete(xhrSuccessStatus[xhr.status] || xhr.status, xhr.statusText, typeof xhr.responseText === "string" ? {text: xhr.responseText} : undefined, xhr.getAllResponseHeaders());
                }
              }
            };
          };
          xhr.onload = callback();
          xhr.onerror = callback("error");
          callback = xhrCallbacks[id] = callback("abort");
          try {
            xhr.send(options.hasContent && options.data || null);
          } catch (e) {
            if (callback) {
              throw e;
            }
          }
        },
        abort: function() {
          if (callback) {
            callback();
          }
        }
      };
    }
  });
  jQuery.ajaxSetup({
    accepts: {script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},
    contents: {script: /(?:java|ecma)script/},
    converters: {"text script": function(text) {
        jQuery.globalEval(text);
        return text;
      }}
  });
  jQuery.ajaxPrefilter("script", function(s) {
    if (s.cache === undefined) {
      s.cache = false;
    }
    if (s.crossDomain) {
      s.type = "GET";
    }
  });
  jQuery.ajaxTransport("script", function(s) {
    if (s.crossDomain) {
      var script,
          callback;
      return {
        send: function(_, complete) {
          script = jQuery("<script>").prop({
            async: true,
            charset: s.scriptCharset,
            src: s.url
          }).on("load error", callback = function(evt) {
            script.remove();
            callback = null;
            if (evt) {
              complete(evt.type === "error" ? 404 : 200, evt.type);
            }
          });
          document.head.appendChild(script[0]);
        },
        abort: function() {
          if (callback) {
            callback();
          }
        }
      };
    }
  });
  var oldCallbacks = [],
      rjsonp = /(=)\?(?=&|$)|\?\?/;
  jQuery.ajaxSetup({
    jsonp: "callback",
    jsonpCallback: function() {
      var callback = oldCallbacks.pop() || (jQuery.expando + "_" + (nonce++));
      this[callback] = true;
      return callback;
    }
  });
  jQuery.ajaxPrefilter("json jsonp", function(s, originalSettings, jqXHR) {
    var callbackName,
        overwritten,
        responseContainer,
        jsonProp = s.jsonp !== false && (rjsonp.test(s.url) ? "url" : typeof s.data === "string" && !(s.contentType || "").indexOf("application/x-www-form-urlencoded") && rjsonp.test(s.data) && "data");
    if (jsonProp || s.dataTypes[0] === "jsonp") {
      callbackName = s.jsonpCallback = jQuery.isFunction(s.jsonpCallback) ? s.jsonpCallback() : s.jsonpCallback;
      if (jsonProp) {
        s[jsonProp] = s[jsonProp].replace(rjsonp, "$1" + callbackName);
      } else if (s.jsonp !== false) {
        s.url += (rquery.test(s.url) ? "&" : "?") + s.jsonp + "=" + callbackName;
      }
      s.converters["script json"] = function() {
        if (!responseContainer) {
          jQuery.error(callbackName + " was not called");
        }
        return responseContainer[0];
      };
      s.dataTypes[0] = "json";
      overwritten = window[callbackName];
      window[callbackName] = function() {
        responseContainer = arguments;
      };
      jqXHR.always(function() {
        window[callbackName] = overwritten;
        if (s[callbackName]) {
          s.jsonpCallback = originalSettings.jsonpCallback;
          oldCallbacks.push(callbackName);
        }
        if (responseContainer && jQuery.isFunction(overwritten)) {
          overwritten(responseContainer[0]);
        }
        responseContainer = overwritten = undefined;
      });
      return "script";
    }
  });
  jQuery.parseHTML = function(data, context, keepScripts) {
    if (!data || typeof data !== "string") {
      return null;
    }
    if (typeof context === "boolean") {
      keepScripts = context;
      context = false;
    }
    context = context || document;
    var parsed = rsingleTag.exec(data),
        scripts = !keepScripts && [];
    if (parsed) {
      return [context.createElement(parsed[1])];
    }
    parsed = jQuery.buildFragment([data], context, scripts);
    if (scripts && scripts.length) {
      jQuery(scripts).remove();
    }
    return jQuery.merge([], parsed.childNodes);
  };
  var _load = jQuery.fn.load;
  jQuery.fn.load = function(url, params, callback) {
    if (typeof url !== "string" && _load) {
      return _load.apply(this, arguments);
    }
    var selector,
        type,
        response,
        self = this,
        off = url.indexOf(" ");
    if (off >= 0) {
      selector = jQuery.trim(url.slice(off));
      url = url.slice(0, off);
    }
    if (jQuery.isFunction(params)) {
      callback = params;
      params = undefined;
    } else if (params && typeof params === "object") {
      type = "POST";
    }
    if (self.length > 0) {
      jQuery.ajax({
        url: url,
        type: type,
        dataType: "html",
        data: params
      }).done(function(responseText) {
        response = arguments;
        self.html(selector ? jQuery("<div>").append(jQuery.parseHTML(responseText)).find(selector) : responseText);
      }).complete(callback && function(jqXHR, status) {
        self.each(callback, response || [jqXHR.responseText, status, jqXHR]);
      });
    }
    return this;
  };
  jQuery.each(["ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend"], function(i, type) {
    jQuery.fn[type] = function(fn) {
      return this.on(type, fn);
    };
  });
  jQuery.expr.filters.animated = function(elem) {
    return jQuery.grep(jQuery.timers, function(fn) {
      return elem === fn.elem;
    }).length;
  };
  var docElem = window.document.documentElement;
  function getWindow(elem) {
    return jQuery.isWindow(elem) ? elem : elem.nodeType === 9 && elem.defaultView;
  }
  jQuery.offset = {setOffset: function(elem, options, i) {
      var curPosition,
          curLeft,
          curCSSTop,
          curTop,
          curOffset,
          curCSSLeft,
          calculatePosition,
          position = jQuery.css(elem, "position"),
          curElem = jQuery(elem),
          props = {};
      if (position === "static") {
        elem.style.position = "relative";
      }
      curOffset = curElem.offset();
      curCSSTop = jQuery.css(elem, "top");
      curCSSLeft = jQuery.css(elem, "left");
      calculatePosition = (position === "absolute" || position === "fixed") && (curCSSTop + curCSSLeft).indexOf("auto") > -1;
      if (calculatePosition) {
        curPosition = curElem.position();
        curTop = curPosition.top;
        curLeft = curPosition.left;
      } else {
        curTop = parseFloat(curCSSTop) || 0;
        curLeft = parseFloat(curCSSLeft) || 0;
      }
      if (jQuery.isFunction(options)) {
        options = options.call(elem, i, curOffset);
      }
      if (options.top != null) {
        props.top = (options.top - curOffset.top) + curTop;
      }
      if (options.left != null) {
        props.left = (options.left - curOffset.left) + curLeft;
      }
      if ("using" in options) {
        options.using.call(elem, props);
      } else {
        curElem.css(props);
      }
    }};
  jQuery.fn.extend({
    offset: function(options) {
      if (arguments.length) {
        return options === undefined ? this : this.each(function(i) {
          jQuery.offset.setOffset(this, options, i);
        });
      }
      var docElem,
          win,
          elem = this[0],
          box = {
            top: 0,
            left: 0
          },
          doc = elem && elem.ownerDocument;
      if (!doc) {
        return;
      }
      docElem = doc.documentElement;
      if (!jQuery.contains(docElem, elem)) {
        return box;
      }
      if (typeof elem.getBoundingClientRect !== strundefined) {
        box = elem.getBoundingClientRect();
      }
      win = getWindow(doc);
      return {
        top: box.top + win.pageYOffset - docElem.clientTop,
        left: box.left + win.pageXOffset - docElem.clientLeft
      };
    },
    position: function() {
      if (!this[0]) {
        return;
      }
      var offsetParent,
          offset,
          elem = this[0],
          parentOffset = {
            top: 0,
            left: 0
          };
      if (jQuery.css(elem, "position") === "fixed") {
        offset = elem.getBoundingClientRect();
      } else {
        offsetParent = this.offsetParent();
        offset = this.offset();
        if (!jQuery.nodeName(offsetParent[0], "html")) {
          parentOffset = offsetParent.offset();
        }
        parentOffset.top += jQuery.css(offsetParent[0], "borderTopWidth", true);
        parentOffset.left += jQuery.css(offsetParent[0], "borderLeftWidth", true);
      }
      return {
        top: offset.top - parentOffset.top - jQuery.css(elem, "marginTop", true),
        left: offset.left - parentOffset.left - jQuery.css(elem, "marginLeft", true)
      };
    },
    offsetParent: function() {
      return this.map(function() {
        var offsetParent = this.offsetParent || docElem;
        while (offsetParent && (!jQuery.nodeName(offsetParent, "html") && jQuery.css(offsetParent, "position") === "static")) {
          offsetParent = offsetParent.offsetParent;
        }
        return offsetParent || docElem;
      });
    }
  });
  jQuery.each({
    scrollLeft: "pageXOffset",
    scrollTop: "pageYOffset"
  }, function(method, prop) {
    var top = "pageYOffset" === prop;
    jQuery.fn[method] = function(val) {
      return access(this, function(elem, method, val) {
        var win = getWindow(elem);
        if (val === undefined) {
          return win ? win[prop] : elem[method];
        }
        if (win) {
          win.scrollTo(!top ? val : window.pageXOffset, top ? val : window.pageYOffset);
        } else {
          elem[method] = val;
        }
      }, method, val, arguments.length, null);
    };
  });
  jQuery.each(["top", "left"], function(i, prop) {
    jQuery.cssHooks[prop] = addGetHookIf(support.pixelPosition, function(elem, computed) {
      if (computed) {
        computed = curCSS(elem, prop);
        return rnumnonpx.test(computed) ? jQuery(elem).position()[prop] + "px" : computed;
      }
    });
  });
  jQuery.each({
    Height: "height",
    Width: "width"
  }, function(name, type) {
    jQuery.each({
      padding: "inner" + name,
      content: type,
      "": "outer" + name
    }, function(defaultExtra, funcName) {
      jQuery.fn[funcName] = function(margin, value) {
        var chainable = arguments.length && (defaultExtra || typeof margin !== "boolean"),
            extra = defaultExtra || (margin === true || value === true ? "margin" : "border");
        return access(this, function(elem, type, value) {
          var doc;
          if (jQuery.isWindow(elem)) {
            return elem.document.documentElement["client" + name];
          }
          if (elem.nodeType === 9) {
            doc = elem.documentElement;
            return Math.max(elem.body["scroll" + name], doc["scroll" + name], elem.body["offset" + name], doc["offset" + name], doc["client" + name]);
          }
          return value === undefined ? jQuery.css(elem, type, extra) : jQuery.style(elem, type, value, extra);
        }, type, chainable ? margin : undefined, chainable, null);
      };
    });
  });
  jQuery.fn.size = function() {
    return this.length;
  };
  jQuery.fn.andSelf = jQuery.fn.addBack;
  if (typeof define === "function" && define.amd) {
    define("19", [], function() {
      return jQuery;
    }) && define("jquery", ["19"], function(m) {
      return m;
    });
  }
  var _jQuery = window.jQuery,
      _$ = window.$;
  jQuery.noConflict = function(deep) {
    if (window.$ === jQuery) {
      window.$ = _$;
    }
    if (deep && window.jQuery === jQuery) {
      window.jQuery = _jQuery;
    }
    return jQuery;
  };
  if (typeof noGlobal === strundefined) {
    window.jQuery = window.$ = jQuery;
  }
  return jQuery;
}));

})();
(function() {
var define = $__System.amdDefine;
(function(deparam) {
  if (typeof require === 'function' && typeof exports === 'object' && typeof module === 'object') {
    var jquery = require('jquery');
    module.exports = deparam(jquery);
  } else if (typeof define === 'function' && define.amd) {
    define("1f", ["19"], function(jquery) {
      return deparam(jquery);
    });
  } else {
    var global = (false || eval)('this');
    global.deparam = deparam(jQuery);
  }
})(function($) {
  var deparam = function(params, coerce) {
    var obj = {},
        coerce_types = {
          'true': !0,
          'false': !1,
          'null': null
        };
    $.each(params.replace(/\+/g, ' ').split('&'), function(j, v) {
      var param = v.split('='),
          key = decodeURIComponent(param[0]),
          val,
          cur = obj,
          i = 0,
          keys = key.split(']['),
          keys_last = keys.length - 1;
      if (/\[/.test(keys[0]) && /\]$/.test(keys[keys_last])) {
        keys[keys_last] = keys[keys_last].replace(/\]$/, '');
        keys = keys.shift().split('[').concat(keys);
        keys_last = keys.length - 1;
      } else {
        keys_last = 0;
      }
      if (param.length === 2) {
        val = decodeURIComponent(param[1]);
        if (coerce) {
          val = val && !isNaN(val) ? +val : val === 'undefined' ? undefined : coerce_types[val] !== undefined ? coerce_types[val] : val;
        }
        if (keys_last) {
          for (; i <= keys_last; i++) {
            key = keys[i] === '' ? cur.length : keys[i];
            cur = cur[key] = i < keys_last ? cur[key] || (keys[i + 1] && isNaN(keys[i + 1]) ? {} : []) : val;
          }
        } else {
          if ($.isArray(obj[key])) {
            obj[key].push(val);
          } else if (obj[key] !== undefined) {
            obj[key] = [obj[key], val];
          } else {
            obj[key] = val;
          }
        }
      } else if (key) {
        obj[key] = coerce ? undefined : '';
      }
    });
    return obj;
  };
  $.fn.deparam = $.deparam = deparam;
  return deparam;
});

})();
$__System.registerDynamic("3f", ["19", "20", "1a", "1e", "23", "1f"], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  var $,
      P,
      seqr,
      ref$,
      runScenario,
      newEnv,
      scenario,
      L,
      runUntilPassed,
      shuffleArray,
      mulsimco2015,
      defaultExperiment,
      freeDriving,
      runWithNewEnv,
      blindPursuit,
      deparam,
      singleScenario,
      memkiller,
      logkiller,
      out$ = typeof exports != 'undefined' && exports || this,
      slice$ = [].slice;
  $ = $__require('19');
  P = $__require('20');
  seqr = $__require('1a');
  ref$ = $__require('1e'), runScenario = ref$.runScenario, newEnv = ref$.newEnv;
  scenario = $__require('23');
  L = function(s) {
    return s;
  };
  runUntilPassed = seqr.bind(function*(scenarioLoader, arg$) {
    var ref$,
        passes,
        ref1$,
        maxRetries,
        currentPasses,
        i$,
        to$,
        retry,
        task,
        result,
        doQuit,
        results$ = [];
    ref$ = arg$ != null ? arg$ : {}, passes = (ref1$ = ref$.passes) != null ? ref1$ : 2, maxRetries = (ref1$ = ref$.maxRetries) != null ? ref1$ : 5;
    currentPasses = 0;
    for (i$ = 1, to$ = Infinity; i$ < to$; ++i$) {
      retry = i$;
      task = runScenario(scenarioLoader);
      result = (yield task.get('done'));
      currentPasses += result.passed;
      doQuit = currentPasses >= passes || retry > maxRetries;
      (yield task);
      if (doQuit) {
        break;
      }
    }
    return results$;
  });
  shuffleArray = function(a) {
    var i,
        j,
        ref$;
    i = a.length;
    while (--i > 0) {
      j = Math.floor(Math.random() * (i + 1));
      ref$ = [a[j], a[i]], a[i] = ref$[0], a[j] = ref$[1];
    }
    return a;
  };
  out$.mulsimco2015 = mulsimco2015 = seqr.bind(function*() {
    var env,
        ntrials,
        scenarios,
        i$,
        len$,
        scn,
        intervals,
        interval;
    env = newEnv();
    (yield scenario.participantInformation((yield env.get('env'))));
    env['let']('destroy');
    (yield env);
    (yield runUntilPassed(scenario.closeTheGap, {passes: 3}));
    (yield runUntilPassed(scenario.throttleAndBrake));
    (yield runUntilPassed(scenario.speedControl));
    (yield runUntilPassed(scenario.blindSpeedControl));
    (yield runUntilPassed(scenario.followInTraffic));
    (yield runUntilPassed(scenario.blindFollowInTraffic));
    ntrials = 4;
    scenarios = [].concat(repeatArray$([scenario.followInTraffic], ntrials)).concat(repeatArray$([scenario.blindFollowInTraffic], ntrials));
    scenarios = shuffleArray(scenarios);
    for (i$ = 0, len$ = scenarios.length; i$ < len$; ++i$) {
      scn = scenarios[i$];
      (yield runScenario(scn));
    }
    intervals = shuffleArray([1, 1, 2, 2, 3, 3]);
    for (i$ = 0, len$ = intervals.length; i$ < len$; ++i$) {
      interval = intervals[i$];
      (yield runScenario(scenario.forcedBlindFollowInTraffic, {interval: interval}));
    }
    env = newEnv();
    (yield scenario.experimentOutro((yield env.get('env'))));
    env['let']('destroy');
    return (yield env);
  });
  out$.defaultExperiment = defaultExperiment = mulsimco2015;
  out$.freeDriving = freeDriving = seqr.bind(function*() {
    return (yield runScenario(scenario.freeDriving));
  });
  runWithNewEnv = seqr.bind(function*(scenario) {
    var args,
        res$,
        i$,
        to$,
        envP,
        env,
        ret;
    res$ = [];
    for (i$ = 1, to$ = arguments.length; i$ < to$; ++i$) {
      res$.push(arguments[i$]);
    }
    args = res$;
    envP = newEnv();
    env = (yield envP.get('env'));
    ret = (yield scenario.apply(null, [env].concat(slice$.call(args))));
    envP['let']('destroy');
    (yield envP);
    return ret;
  });
  out$.blindPursuit = blindPursuit = seqr.bind(function*() {
    var totalScore,
        runPursuitScenario,
        res,
        frequency,
        nBlocks,
        trialsPerBlock,
        i$,
        block,
        j$,
        trial,
        env;
    (yield runWithNewEnv(scenario.participantInformationBlindPursuit));
    totalScore = {
      correct: 0,
      incorrect: 0
    };
    (yield runWithNewEnv(scenario.soundSpook, {preIntro: true}));
    runPursuitScenario = seqr.bind(function*() {
      var args,
          res$,
          i$,
          to$,
          task,
          env,
          res,
          totalPercentage;
      res$ = [];
      for (i$ = 0, to$ = arguments.length; i$ < to$; ++i$) {
        res$.push(arguments[i$]);
      }
      args = res$;
      task = runScenario.apply(null, args);
      env = (yield task.get('env'));
      res = (yield task.get('done'));
      totalScore.correct += res.result.score.correct;
      totalScore.incorrect += res.result.score.incorrect;
      totalPercentage = totalScore.correct / (totalScore.correct + totalScore.incorrect) * 100;
      res.outro('content').append($(env.L("%blindPursuit.totalScore", {score: totalPercentage})));
      (yield task);
      return res;
    });
    res = (yield runPursuitScenario(scenario.pursuitDiscriminationPractice));
    frequency = res.result.estimatedFrequency;
    nBlocks = 2;
    trialsPerBlock = 2;
    for (i$ = 0; i$ < nBlocks; ++i$) {
      block = i$;
      for (j$ = 0; j$ < trialsPerBlock; ++j$) {
        trial = j$;
        (yield runPursuitScenario(scenario.pursuitDiscrimination, {frequency: frequency}));
      }
      (yield runWithNewEnv(scenario.soundSpook));
    }
    env = newEnv();
    (yield scenario.experimentOutro((yield env.get('env')), function(env) {
      var totalPercentage;
      totalPercentage = totalScore.correct / (totalScore.correct + totalScore.incorrect) * 100;
      return this('content').append(env.L('%blindPursuit.finalScore', {score: totalPercentage}));
    }));
    env['let']('destroy');
    return (yield env);
  });
  deparam = $__require('1f');
  out$.singleScenario = singleScenario = seqr.bind(function*() {
    var opts,
        scn,
        results$ = [];
    opts = deparam(window.location.search.substring(1));
    scn = scenario[opts.singleScenario];
    for (; ; ) {
      results$.push((yield runScenario(scn)));
    }
    return results$;
  });
  out$.memkiller = memkiller = seqr.bind(function*() {
    var loader,
        i$,
        i,
        j$,
        fn$ = function*() {
          var runner,
              scn,
              intro,
              outro;
          runner = runScenario(loader);
          scn = (yield runner.get('ready'))[0];
          console.log("Got scenario");
          intro = (yield runner.get('intro'))[0];
          if (intro['let']) {
            intro['let']('accept');
          }
          (yield P.delay(1000));
          scn['let']('done', {
            passed: false,
            outro: {title: "Yay"}
          });
          runner['let']('done');
          outro = (yield runner.get('outro'))[0];
          outro['let']('accept');
          console.log("Running");
          (yield runner);
          console.log("Done");
        };
    loader = scenario.blindFollowInTraffic;
    for (i$ = 1; i$ <= 10; ++i$) {
      i = i$;
      console.log(i);
      (yield seqr.bind(fn$)());
      console.log("Memory usage: ", window.performance.memory.totalJSHeapSize / 1024 / 1024);
      if (window.gc) {
        for (j$ = 0; j$ < 10; ++j$) {
          i = j$;
          window.gc();
        }
        console.log("Memory usage (after gc): ", window.performance.memory.totalJSHeapSize / 1024 / 1024);
      }
    }
    return i;
  });
  out$.logkiller = logkiller = seqr.bind(function*() {
    var scope,
        env,
        i$,
        i;
    scope = newEnv();
    env = (yield scope.get('env'));
    for (i$ = 0; i$ <= 1000; ++i$) {
      i = i$;
      env.logger.write({foo: "bar"});
    }
    scope['let']('destroy');
    (yield scope);
    console.log("Done");
  });
  function repeatArray$(arr, n) {
    for (var r = []; n > 0; (n >>= 1) && (arr = arr.concat(arr)))
      if (n & 1)
        r.push.apply(r, arr);
    return r;
  }
  return module.exports;
});

$__System.registerDynamic("40", ["41"], true, function($__require, exports, module) {
  "use strict";
  ;
  var define,
      global = this,
      GLOBAL = this;
  var util = $__require('41');
  var schedule;
  var noAsyncScheduler = function() {
    throw new Error("No async scheduler available\u000a\u000a    See http://goo.gl/MqrFmX\u000a");
  };
  if (util.isNode && typeof MutationObserver === "undefined") {
    var GlobalSetImmediate = global.setImmediate;
    var ProcessNextTick = process.nextTick;
    schedule = util.isRecentNode ? function(fn) {
      GlobalSetImmediate.call(global, fn);
    } : function(fn) {
      ProcessNextTick.call(process, fn);
    };
  } else if ((typeof MutationObserver !== "undefined") && !(typeof window !== "undefined" && window.navigator && window.navigator.standalone)) {
    schedule = (function() {
      var div = document.createElement("div");
      var opts = {attributes: true};
      var toggleScheduled = false;
      var div2 = document.createElement("div");
      var o2 = new MutationObserver(function() {
        div.classList.toggle("foo");
        toggleScheduled = false;
      });
      o2.observe(div2, opts);
      var scheduleToggle = function() {
        if (toggleScheduled)
          return;
        toggleScheduled = true;
        div2.classList.toggle("foo");
      };
      return function schedule(fn) {
        var o = new MutationObserver(function() {
          o.disconnect();
          fn();
        });
        o.observe(div, opts);
        scheduleToggle();
      };
    })();
  } else if (typeof setImmediate !== "undefined") {
    schedule = function(fn) {
      setImmediate(fn);
    };
  } else if (typeof setTimeout !== "undefined") {
    schedule = function(fn) {
      setTimeout(fn, 0);
    };
  } else {
    schedule = noAsyncScheduler;
  }
  module.exports = schedule;
  return module.exports;
});

$__System.registerDynamic("42", [], true, function($__require, exports, module) {
  "use strict";
  ;
  var define,
      global = this,
      GLOBAL = this;
  function arrayMove(src, srcIndex, dst, dstIndex, len) {
    for (var j = 0; j < len; ++j) {
      dst[j + dstIndex] = src[j + srcIndex];
      src[j + srcIndex] = void 0;
    }
  }
  function Queue(capacity) {
    this._capacity = capacity;
    this._length = 0;
    this._front = 0;
  }
  Queue.prototype._willBeOverCapacity = function(size) {
    return this._capacity < size;
  };
  Queue.prototype._pushOne = function(arg) {
    var length = this.length();
    this._checkCapacity(length + 1);
    var i = (this._front + length) & (this._capacity - 1);
    this[i] = arg;
    this._length = length + 1;
  };
  Queue.prototype._unshiftOne = function(value) {
    var capacity = this._capacity;
    this._checkCapacity(this.length() + 1);
    var front = this._front;
    var i = ((((front - 1) & (capacity - 1)) ^ capacity) - capacity);
    this[i] = value;
    this._front = i;
    this._length = this.length() + 1;
  };
  Queue.prototype.unshift = function(fn, receiver, arg) {
    this._unshiftOne(arg);
    this._unshiftOne(receiver);
    this._unshiftOne(fn);
  };
  Queue.prototype.push = function(fn, receiver, arg) {
    var length = this.length() + 3;
    if (this._willBeOverCapacity(length)) {
      this._pushOne(fn);
      this._pushOne(receiver);
      this._pushOne(arg);
      return;
    }
    var j = this._front + length - 3;
    this._checkCapacity(length);
    var wrapMask = this._capacity - 1;
    this[(j + 0) & wrapMask] = fn;
    this[(j + 1) & wrapMask] = receiver;
    this[(j + 2) & wrapMask] = arg;
    this._length = length;
  };
  Queue.prototype.shift = function() {
    var front = this._front,
        ret = this[front];
    this[front] = undefined;
    this._front = (front + 1) & (this._capacity - 1);
    this._length--;
    return ret;
  };
  Queue.prototype.length = function() {
    return this._length;
  };
  Queue.prototype._checkCapacity = function(size) {
    if (this._capacity < size) {
      this._resizeTo(this._capacity << 1);
    }
  };
  Queue.prototype._resizeTo = function(capacity) {
    var oldCapacity = this._capacity;
    this._capacity = capacity;
    var front = this._front;
    var length = this._length;
    var moveItemsCount = (front + length) & (oldCapacity - 1);
    arrayMove(this, 0, this, oldCapacity, moveItemsCount);
  };
  module.exports = Queue;
  return module.exports;
});

$__System.registerDynamic("43", ["40", "42", "41"], true, function($__require, exports, module) {
  "use strict";
  ;
  var define,
      global = this,
      GLOBAL = this;
  var firstLineError;
  try {
    throw new Error();
  } catch (e) {
    firstLineError = e;
  }
  var schedule = $__require('40');
  var Queue = $__require('42');
  var util = $__require('41');
  function Async() {
    this._isTickUsed = false;
    this._lateQueue = new Queue(16);
    this._normalQueue = new Queue(16);
    this._haveDrainedQueues = false;
    this._trampolineEnabled = true;
    var self = this;
    this.drainQueues = function() {
      self._drainQueues();
    };
    this._schedule = schedule;
  }
  Async.prototype.enableTrampoline = function() {
    this._trampolineEnabled = true;
  };
  Async.prototype.disableTrampolineIfNecessary = function() {
    if (util.hasDevTools) {
      this._trampolineEnabled = false;
    }
  };
  Async.prototype.haveItemsQueued = function() {
    return this._isTickUsed || this._haveDrainedQueues;
  };
  Async.prototype.fatalError = function(e, isNode) {
    if (isNode) {
      process.stderr.write("Fatal " + (e instanceof Error ? e.stack : e) + "\n");
      process.exit(2);
    } else {
      this.throwLater(e);
    }
  };
  Async.prototype.throwLater = function(fn, arg) {
    if (arguments.length === 1) {
      arg = fn;
      fn = function() {
        throw arg;
      };
    }
    if (typeof setTimeout !== "undefined") {
      setTimeout(function() {
        fn(arg);
      }, 0);
    } else
      try {
        this._schedule(function() {
          fn(arg);
        });
      } catch (e) {
        throw new Error("No async scheduler available\u000a\u000a    See http://goo.gl/MqrFmX\u000a");
      }
  };
  function AsyncInvokeLater(fn, receiver, arg) {
    this._lateQueue.push(fn, receiver, arg);
    this._queueTick();
  }
  function AsyncInvoke(fn, receiver, arg) {
    this._normalQueue.push(fn, receiver, arg);
    this._queueTick();
  }
  function AsyncSettlePromises(promise) {
    this._normalQueue._pushOne(promise);
    this._queueTick();
  }
  if (!util.hasDevTools) {
    Async.prototype.invokeLater = AsyncInvokeLater;
    Async.prototype.invoke = AsyncInvoke;
    Async.prototype.settlePromises = AsyncSettlePromises;
  } else {
    Async.prototype.invokeLater = function(fn, receiver, arg) {
      if (this._trampolineEnabled) {
        AsyncInvokeLater.call(this, fn, receiver, arg);
      } else {
        this._schedule(function() {
          setTimeout(function() {
            fn.call(receiver, arg);
          }, 100);
        });
      }
    };
    Async.prototype.invoke = function(fn, receiver, arg) {
      if (this._trampolineEnabled) {
        AsyncInvoke.call(this, fn, receiver, arg);
      } else {
        this._schedule(function() {
          fn.call(receiver, arg);
        });
      }
    };
    Async.prototype.settlePromises = function(promise) {
      if (this._trampolineEnabled) {
        AsyncSettlePromises.call(this, promise);
      } else {
        this._schedule(function() {
          promise._settlePromises();
        });
      }
    };
  }
  Async.prototype.invokeFirst = function(fn, receiver, arg) {
    this._normalQueue.unshift(fn, receiver, arg);
    this._queueTick();
  };
  Async.prototype._drainQueue = function(queue) {
    while (queue.length() > 0) {
      var fn = queue.shift();
      if (typeof fn !== "function") {
        fn._settlePromises();
        continue;
      }
      var receiver = queue.shift();
      var arg = queue.shift();
      fn.call(receiver, arg);
    }
  };
  Async.prototype._drainQueues = function() {
    this._drainQueue(this._normalQueue);
    this._reset();
    this._haveDrainedQueues = true;
    this._drainQueue(this._lateQueue);
  };
  Async.prototype._queueTick = function() {
    if (!this._isTickUsed) {
      this._isTickUsed = true;
      this._schedule(this.drainQueues);
    }
  };
  Async.prototype._reset = function() {
    this._isTickUsed = false;
  };
  module.exports = Async;
  module.exports.firstLineError = firstLineError;
  return module.exports;
});

$__System.registerDynamic("44", ["41"], true, function($__require, exports, module) {
  "use strict";
  ;
  var define,
      global = this,
      GLOBAL = this;
  module.exports = function(Promise, INTERNAL) {
    var util = $__require('41');
    var errorObj = util.errorObj;
    var isObject = util.isObject;
    function tryConvertToPromise(obj, context) {
      if (isObject(obj)) {
        if (obj instanceof Promise)
          return obj;
        var then = getThen(obj);
        if (then === errorObj) {
          if (context)
            context._pushContext();
          var ret = Promise.reject(then.e);
          if (context)
            context._popContext();
          return ret;
        } else if (typeof then === "function") {
          if (isAnyBluebirdPromise(obj)) {
            var ret = new Promise(INTERNAL);
            obj._then(ret._fulfill, ret._reject, undefined, ret, null);
            return ret;
          }
          return doThenable(obj, then, context);
        }
      }
      return obj;
    }
    function doGetThen(obj) {
      return obj.then;
    }
    function getThen(obj) {
      try {
        return doGetThen(obj);
      } catch (e) {
        errorObj.e = e;
        return errorObj;
      }
    }
    var hasProp = {}.hasOwnProperty;
    function isAnyBluebirdPromise(obj) {
      return hasProp.call(obj, "_promise0");
    }
    function doThenable(x, then, context) {
      var promise = new Promise(INTERNAL);
      var ret = promise;
      if (context)
        context._pushContext();
      promise._captureStackTrace();
      if (context)
        context._popContext();
      var synchronous = true;
      var result = util.tryCatch(then).call(x, resolve, reject);
      synchronous = false;
      if (promise && result === errorObj) {
        promise._rejectCallback(result.e, true, true);
        promise = null;
      }
      function resolve(value) {
        if (!promise)
          return;
        promise._resolveCallback(value);
        promise = null;
      }
      function reject(reason) {
        if (!promise)
          return;
        promise._rejectCallback(reason, synchronous, true);
        promise = null;
      }
      return ret;
    }
    return tryConvertToPromise;
  };
  return module.exports;
});

$__System.registerDynamic("45", ["41"], true, function($__require, exports, module) {
  "use strict";
  ;
  var define,
      global = this,
      GLOBAL = this;
  module.exports = function(Promise, INTERNAL, tryConvertToPromise, apiRejection, Proxyable) {
    var util = $__require('41');
    var isArray = util.isArray;
    function toResolutionValue(val) {
      switch (val) {
        case -2:
          return [];
        case -3:
          return {};
      }
    }
    function PromiseArray(values) {
      var promise = this._promise = new Promise(INTERNAL);
      if (values instanceof Promise) {
        promise._propagateFrom(values, 3);
      }
      promise._setOnCancel(this);
      this._values = values;
      this._length = 0;
      this._totalResolved = 0;
      this._init(undefined, -2);
    }
    util.inherits(PromiseArray, Proxyable);
    PromiseArray.prototype.length = function() {
      return this._length;
    };
    PromiseArray.prototype.promise = function() {
      return this._promise;
    };
    PromiseArray.prototype._init = function init(_, resolveValueIfEmpty) {
      var values = tryConvertToPromise(this._values, this._promise);
      if (values instanceof Promise) {
        values = values._target();
        var bitField = values._bitField;
        ;
        this._values = values;
        if (((bitField & 50397184) === 0)) {
          this._promise._setAsyncGuaranteed();
          return values._then(init, this._reject, undefined, this, resolveValueIfEmpty);
        } else if (((bitField & 33554432) !== 0)) {
          values = values._value();
        } else if (((bitField & 16777216) !== 0)) {
          return this._reject(values._reason());
        } else {
          return this._cancel();
        }
      }
      values = util.asArray(values);
      if (values === null) {
        var err = apiRejection("expecting an array or an iterable object but got " + util.classString(values)).reason();
        this._promise._rejectCallback(err, false);
        return;
      }
      if (values.length === 0) {
        if (resolveValueIfEmpty === -5) {
          this._resolveEmptyArray();
        } else {
          this._resolve(toResolutionValue(resolveValueIfEmpty));
        }
        return;
      }
      this._iterate(values);
    };
    PromiseArray.prototype._iterate = function(values) {
      var len = this.getActualLength(values.length);
      this._length = len;
      this._values = this.shouldCopyValues() ? new Array(len) : this._values;
      var result = this._promise;
      var isResolved = false;
      var bitField = null;
      for (var i = 0; i < len; ++i) {
        var maybePromise = tryConvertToPromise(values[i], result);
        if (maybePromise instanceof Promise) {
          maybePromise = maybePromise._target();
          bitField = maybePromise._bitField;
        } else {
          bitField = null;
        }
        if (isResolved) {
          if (bitField !== null) {
            maybePromise.suppressUnhandledRejections();
          }
        } else if (bitField !== null) {
          if (((bitField & 50397184) === 0)) {
            maybePromise._proxy(this, i);
            this._values[i] = maybePromise;
          } else if (((bitField & 33554432) !== 0)) {
            isResolved = this._promiseFulfilled(maybePromise._value(), i);
          } else if (((bitField & 16777216) !== 0)) {
            isResolved = this._promiseRejected(maybePromise._reason(), i);
          } else {
            isResolved = this._promiseCancelled(i);
          }
        } else {
          isResolved = this._promiseFulfilled(maybePromise, i);
        }
      }
      if (!isResolved)
        result._setAsyncGuaranteed();
    };
    PromiseArray.prototype._isResolved = function() {
      return this._values === null;
    };
    PromiseArray.prototype._resolve = function(value) {
      this._values = null;
      this._promise._fulfill(value);
    };
    PromiseArray.prototype._cancel = function() {
      if (this._isResolved() || !this._promise.isCancellable())
        return;
      this._values = null;
      this._promise._cancel();
    };
    PromiseArray.prototype._reject = function(reason) {
      this._values = null;
      this._promise._rejectCallback(reason, false);
    };
    PromiseArray.prototype._promiseFulfilled = function(value, index) {
      this._values[index] = value;
      var totalResolved = ++this._totalResolved;
      if (totalResolved >= this._length) {
        this._resolve(this._values);
        return true;
      }
      return false;
    };
    PromiseArray.prototype._promiseCancelled = function() {
      this._cancel();
      return true;
    };
    PromiseArray.prototype._promiseRejected = function(reason) {
      this._totalResolved++;
      this._reject(reason);
      return true;
    };
    PromiseArray.prototype._resultCancelled = function() {
      if (this._isResolved())
        return;
      var values = this._values;
      this._cancel();
      if (values instanceof Promise) {
        values.cancel();
      } else {
        for (var i = 0; i < values.length; ++i) {
          if (values[i] instanceof Promise) {
            values[i].cancel();
          }
        }
      }
    };
    PromiseArray.prototype.shouldCopyValues = function() {
      return true;
    };
    PromiseArray.prototype.getActualLength = function(len) {
      return len;
    };
    return PromiseArray;
  };
  return module.exports;
});

$__System.registerDynamic("46", [], true, function($__require, exports, module) {
  "use strict";
  ;
  var define,
      global = this,
      GLOBAL = this;
  module.exports = function(Promise) {
    var longStackTraces = false;
    var contextStack = [];
    Promise.prototype._promiseCreated = function() {};
    Promise.prototype._pushContext = function() {};
    Promise.prototype._popContext = function() {
      return null;
    };
    Promise._peekContext = Promise.prototype._peekContext = function() {};
    function Context() {
      this._trace = new Context.CapturedTrace(peekContext());
    }
    Context.prototype._pushContext = function() {
      if (this._trace !== undefined) {
        this._trace._promiseCreated = null;
        contextStack.push(this._trace);
      }
    };
    Context.prototype._popContext = function() {
      if (this._trace !== undefined) {
        var trace = contextStack.pop();
        var ret = trace._promiseCreated;
        trace._promiseCreated = null;
        return ret;
      }
      return null;
    };
    function createContext() {
      if (longStackTraces)
        return new Context();
    }
    function peekContext() {
      var lastIndex = contextStack.length - 1;
      if (lastIndex >= 0) {
        return contextStack[lastIndex];
      }
      return undefined;
    }
    Context.CapturedTrace = null;
    Context.create = createContext;
    Context.deactivateLongStackTraces = function() {};
    Context.activateLongStackTraces = function() {
      var Promise_pushContext = Promise.prototype._pushContext;
      var Promise_popContext = Promise.prototype._popContext;
      var Promise_PeekContext = Promise._peekContext;
      var Promise_peekContext = Promise.prototype._peekContext;
      var Promise_promiseCreated = Promise.prototype._promiseCreated;
      Context.deactivateLongStackTraces = function() {
        Promise.prototype._pushContext = Promise_pushContext;
        Promise.prototype._popContext = Promise_popContext;
        Promise._peekContext = Promise_PeekContext;
        Promise.prototype._peekContext = Promise_peekContext;
        Promise.prototype._promiseCreated = Promise_promiseCreated;
        longStackTraces = false;
      };
      longStackTraces = true;
      Promise.prototype._pushContext = Context.prototype._pushContext;
      Promise.prototype._popContext = Context.prototype._popContext;
      Promise._peekContext = Promise.prototype._peekContext = peekContext;
      Promise.prototype._promiseCreated = function() {
        var ctx = this._peekContext();
        if (ctx && ctx._promiseCreated == null)
          ctx._promiseCreated = this;
      };
    };
    return Context;
  };
  return module.exports;
});

$__System.registerDynamic("47", ["48", "41"], true, function($__require, exports, module) {
  "use strict";
  ;
  var define,
      global = this,
      GLOBAL = this;
  module.exports = function(Promise, Context) {
    var getDomain = Promise._getDomain;
    var async = Promise._async;
    var Warning = $__require('48').Warning;
    var util = $__require('41');
    var canAttachTrace = util.canAttachTrace;
    var unhandledRejectionHandled;
    var possiblyUnhandledRejection;
    var bluebirdFramePattern = /[\\\/]bluebird[\\\/]js[\\\/](release|debug|instrumented)/;
    var stackFramePattern = null;
    var formatStack = null;
    var indentStackFrames = false;
    var printWarning;
    var debugging = !!(util.env("BLUEBIRD_DEBUG") != 0 && (false || util.env("BLUEBIRD_DEBUG") || util.env("NODE_ENV") === "development"));
    var warnings = !!(util.env("BLUEBIRD_WARNINGS") != 0 && (debugging || util.env("BLUEBIRD_WARNINGS")));
    var longStackTraces = !!(util.env("BLUEBIRD_LONG_STACK_TRACES") != 0 && (debugging || util.env("BLUEBIRD_LONG_STACK_TRACES")));
    var wForgottenReturn = util.env("BLUEBIRD_W_FORGOTTEN_RETURN") != 0 && (warnings || !!util.env("BLUEBIRD_W_FORGOTTEN_RETURN"));
    Promise.prototype.suppressUnhandledRejections = function() {
      var target = this._target();
      target._bitField = ((target._bitField & (~1048576)) | 524288);
    };
    Promise.prototype._ensurePossibleRejectionHandled = function() {
      if ((this._bitField & 524288) !== 0)
        return;
      this._setRejectionIsUnhandled();
      async.invokeLater(this._notifyUnhandledRejection, this, undefined);
    };
    Promise.prototype._notifyUnhandledRejectionIsHandled = function() {
      fireRejectionEvent("rejectionHandled", unhandledRejectionHandled, undefined, this);
    };
    Promise.prototype._setReturnedNonUndefined = function() {
      this._bitField = this._bitField | 268435456;
    };
    Promise.prototype._returnedNonUndefined = function() {
      return (this._bitField & 268435456) !== 0;
    };
    Promise.prototype._notifyUnhandledRejection = function() {
      if (this._isRejectionUnhandled()) {
        var reason = this._settledValue();
        this._setUnhandledRejectionIsNotified();
        fireRejectionEvent("unhandledRejection", possiblyUnhandledRejection, reason, this);
      }
    };
    Promise.prototype._setUnhandledRejectionIsNotified = function() {
      this._bitField = this._bitField | 262144;
    };
    Promise.prototype._unsetUnhandledRejectionIsNotified = function() {
      this._bitField = this._bitField & (~262144);
    };
    Promise.prototype._isUnhandledRejectionNotified = function() {
      return (this._bitField & 262144) > 0;
    };
    Promise.prototype._setRejectionIsUnhandled = function() {
      this._bitField = this._bitField | 1048576;
    };
    Promise.prototype._unsetRejectionIsUnhandled = function() {
      this._bitField = this._bitField & (~1048576);
      if (this._isUnhandledRejectionNotified()) {
        this._unsetUnhandledRejectionIsNotified();
        this._notifyUnhandledRejectionIsHandled();
      }
    };
    Promise.prototype._isRejectionUnhandled = function() {
      return (this._bitField & 1048576) > 0;
    };
    Promise.prototype._warn = function(message, shouldUseOwnTrace, promise) {
      return warn(message, shouldUseOwnTrace, promise || this);
    };
    Promise.onPossiblyUnhandledRejection = function(fn) {
      var domain = getDomain();
      possiblyUnhandledRejection = typeof fn === "function" ? (domain === null ? fn : domain.bind(fn)) : undefined;
    };
    Promise.onUnhandledRejectionHandled = function(fn) {
      var domain = getDomain();
      unhandledRejectionHandled = typeof fn === "function" ? (domain === null ? fn : domain.bind(fn)) : undefined;
    };
    var disableLongStackTraces = function() {};
    Promise.longStackTraces = function() {
      if (async.haveItemsQueued() && !config.longStackTraces) {
        throw new Error("cannot enable long stack traces after promises have been created\u000a\u000a    See http://goo.gl/MqrFmX\u000a");
      }
      if (!config.longStackTraces && longStackTracesIsSupported()) {
        var Promise_captureStackTrace = Promise.prototype._captureStackTrace;
        var Promise_attachExtraTrace = Promise.prototype._attachExtraTrace;
        config.longStackTraces = true;
        disableLongStackTraces = function() {
          if (async.haveItemsQueued() && !config.longStackTraces) {
            throw new Error("cannot enable long stack traces after promises have been created\u000a\u000a    See http://goo.gl/MqrFmX\u000a");
          }
          Promise.prototype._captureStackTrace = Promise_captureStackTrace;
          Promise.prototype._attachExtraTrace = Promise_attachExtraTrace;
          Context.deactivateLongStackTraces();
          async.enableTrampoline();
          config.longStackTraces = false;
        };
        Promise.prototype._captureStackTrace = longStackTracesCaptureStackTrace;
        Promise.prototype._attachExtraTrace = longStackTracesAttachExtraTrace;
        Context.activateLongStackTraces();
        async.disableTrampolineIfNecessary();
      }
    };
    Promise.hasLongStackTraces = function() {
      return config.longStackTraces && longStackTracesIsSupported();
    };
    var fireDomEvent = (function() {
      try {
        var event = document.createEvent("CustomEvent");
        event.initCustomEvent("testingtheevent", false, true, {});
        util.global.dispatchEvent(event);
        return function(name, event) {
          var domEvent = document.createEvent("CustomEvent");
          domEvent.initCustomEvent(name.toLowerCase(), false, true, event);
          return !util.global.dispatchEvent(domEvent);
        };
      } catch (e) {}
      return function() {
        return false;
      };
    })();
    var fireGlobalEvent = (function() {
      if (util.isNode) {
        return function() {
          return process.emit.apply(process, arguments);
        };
      } else {
        if (!util.global) {
          return function() {
            return false;
          };
        }
        return function(name) {
          var methodName = "on" + name.toLowerCase();
          var method = util.global[methodName];
          if (!method)
            return false;
          method.apply(util.global, [].slice.call(arguments, 1));
          return true;
        };
      }
    })();
    function generatePromiseLifecycleEventObject(name, promise) {
      return {promise: promise};
    }
    var eventToObjectGenerator = {
      promiseCreated: generatePromiseLifecycleEventObject,
      promiseFulfilled: generatePromiseLifecycleEventObject,
      promiseRejected: generatePromiseLifecycleEventObject,
      promiseResolved: generatePromiseLifecycleEventObject,
      promiseCancelled: generatePromiseLifecycleEventObject,
      promiseChained: function(name, promise, child) {
        return {
          promise: promise,
          child: child
        };
      },
      warning: function(name, warning) {
        return {warning: warning};
      },
      unhandledRejection: function(name, reason, promise) {
        return {
          reason: reason,
          promise: promise
        };
      },
      rejectionHandled: generatePromiseLifecycleEventObject
    };
    var activeFireEvent = function(name) {
      var globalEventFired = false;
      try {
        globalEventFired = fireGlobalEvent.apply(null, arguments);
      } catch (e) {
        async.throwLater(e);
        globalEventFired = true;
      }
      var domEventFired = false;
      try {
        domEventFired = fireDomEvent(name, eventToObjectGenerator[name].apply(null, arguments));
      } catch (e) {
        async.throwLater(e);
        domEventFired = true;
      }
      return domEventFired || globalEventFired;
    };
    Promise.config = function(opts) {
      opts = Object(opts);
      if ("longStackTraces" in opts) {
        if (opts.longStackTraces) {
          Promise.longStackTraces();
        } else if (!opts.longStackTraces && Promise.hasLongStackTraces()) {
          disableLongStackTraces();
        }
      }
      if ("warnings" in opts) {
        var warningsOption = opts.warnings;
        config.warnings = !!warningsOption;
        wForgottenReturn = config.warnings;
        if (util.isObject(warningsOption)) {
          if ("wForgottenReturn" in warningsOption) {
            wForgottenReturn = !!warningsOption.wForgottenReturn;
          }
        }
      }
      if ("cancellation" in opts && opts.cancellation && !config.cancellation) {
        if (async.haveItemsQueued()) {
          throw new Error("cannot enable cancellation after promises are in use");
        }
        Promise.prototype._clearCancellationData = cancellationClearCancellationData;
        Promise.prototype._propagateFrom = cancellationPropagateFrom;
        Promise.prototype._onCancel = cancellationOnCancel;
        Promise.prototype._setOnCancel = cancellationSetOnCancel;
        Promise.prototype._attachCancellationCallback = cancellationAttachCancellationCallback;
        Promise.prototype._execute = cancellationExecute;
        propagateFromFunction = cancellationPropagateFrom;
        config.cancellation = true;
      }
      if ("monitoring" in opts) {
        if (opts.monitoring && !config.monitoring) {
          config.monitoring = true;
          Promise.prototype._fireEvent = activeFireEvent;
        } else if (!opts.monitoring && config.monitoring) {
          config.monitoring = false;
          Promise.prototype._fireEvent = defaultFireEvent;
        }
      }
    };
    function defaultFireEvent() {
      return false;
    }
    Promise.prototype._fireEvent = defaultFireEvent;
    Promise.prototype._execute = function(executor, resolve, reject) {
      try {
        executor(resolve, reject);
      } catch (e) {
        return e;
      }
    };
    Promise.prototype._onCancel = function() {};
    Promise.prototype._setOnCancel = function(handler) {
      ;
    };
    Promise.prototype._attachCancellationCallback = function(onCancel) {
      ;
    };
    Promise.prototype._captureStackTrace = function() {};
    Promise.prototype._attachExtraTrace = function() {};
    Promise.prototype._clearCancellationData = function() {};
    Promise.prototype._propagateFrom = function(parent, flags) {
      ;
      ;
    };
    function cancellationExecute(executor, resolve, reject) {
      var promise = this;
      try {
        executor(resolve, reject, function(onCancel) {
          if (typeof onCancel !== "function") {
            throw new TypeError("onCancel must be a function, got: " + util.toString(onCancel));
          }
          promise._attachCancellationCallback(onCancel);
        });
      } catch (e) {
        return e;
      }
    }
    function cancellationAttachCancellationCallback(onCancel) {
      if (!this.isCancellable())
        return this;
      var previousOnCancel = this._onCancel();
      if (previousOnCancel !== undefined) {
        if (util.isArray(previousOnCancel)) {
          previousOnCancel.push(onCancel);
        } else {
          this._setOnCancel([previousOnCancel, onCancel]);
        }
      } else {
        this._setOnCancel(onCancel);
      }
    }
    function cancellationOnCancel() {
      return this._onCancelField;
    }
    function cancellationSetOnCancel(onCancel) {
      this._onCancelField = onCancel;
    }
    function cancellationClearCancellationData() {
      this._cancellationParent = undefined;
      this._onCancelField = undefined;
    }
    function cancellationPropagateFrom(parent, flags) {
      if ((flags & 1) !== 0) {
        this._cancellationParent = parent;
        var branchesRemainingToCancel = parent._branchesRemainingToCancel;
        if (branchesRemainingToCancel === undefined) {
          branchesRemainingToCancel = 0;
        }
        parent._branchesRemainingToCancel = branchesRemainingToCancel + 1;
      }
      if ((flags & 2) !== 0 && parent._isBound()) {
        this._setBoundTo(parent._boundTo);
      }
    }
    function bindingPropagateFrom(parent, flags) {
      if ((flags & 2) !== 0 && parent._isBound()) {
        this._setBoundTo(parent._boundTo);
      }
    }
    var propagateFromFunction = bindingPropagateFrom;
    function boundValueFunction() {
      var ret = this._boundTo;
      if (ret !== undefined) {
        if (ret instanceof Promise) {
          if (ret.isFulfilled()) {
            return ret.value();
          } else {
            return undefined;
          }
        }
      }
      return ret;
    }
    function longStackTracesCaptureStackTrace() {
      this._trace = new CapturedTrace(this._peekContext());
    }
    function longStackTracesAttachExtraTrace(error, ignoreSelf) {
      if (canAttachTrace(error)) {
        var trace = this._trace;
        if (trace !== undefined) {
          if (ignoreSelf)
            trace = trace._parent;
        }
        if (trace !== undefined) {
          trace.attachExtraTrace(error);
        } else if (!error.__stackCleaned__) {
          var parsed = parseStackAndMessage(error);
          util.notEnumerableProp(error, "stack", parsed.message + "\n" + parsed.stack.join("\n"));
          util.notEnumerableProp(error, "__stackCleaned__", true);
        }
      }
    }
    function checkForgottenReturns(returnValue, promiseCreated, name, promise, parent) {
      if (returnValue === undefined && promiseCreated !== null && wForgottenReturn) {
        if (parent !== undefined && parent._returnedNonUndefined())
          return;
        var bitField = promise._bitField;
        if ((bitField & 65535) === 0)
          return;
        if (name)
          name = name + " ";
        var msg = "a promise was created in a " + name + "handler but was not returned from it";
        promise._warn(msg, true, promiseCreated);
      }
    }
    function deprecated(name, replacement) {
      var message = name + " is deprecated and will be removed in a future version.";
      if (replacement)
        message += " Use " + replacement + " instead.";
      return warn(message);
    }
    function warn(message, shouldUseOwnTrace, promise) {
      if (!config.warnings)
        return;
      var warning = new Warning(message);
      var ctx;
      if (shouldUseOwnTrace) {
        promise._attachExtraTrace(warning);
      } else if (config.longStackTraces && (ctx = Promise._peekContext())) {
        ctx.attachExtraTrace(warning);
      } else {
        var parsed = parseStackAndMessage(warning);
        warning.stack = parsed.message + "\n" + parsed.stack.join("\n");
      }
      if (!activeFireEvent("warning", warning)) {
        formatAndLogError(warning, "", true);
      }
    }
    function reconstructStack(message, stacks) {
      for (var i = 0; i < stacks.length - 1; ++i) {
        stacks[i].push("From previous event:");
        stacks[i] = stacks[i].join("\n");
      }
      if (i < stacks.length) {
        stacks[i] = stacks[i].join("\n");
      }
      return message + "\n" + stacks.join("\n");
    }
    function removeDuplicateOrEmptyJumps(stacks) {
      for (var i = 0; i < stacks.length; ++i) {
        if (stacks[i].length === 0 || ((i + 1 < stacks.length) && stacks[i][0] === stacks[i + 1][0])) {
          stacks.splice(i, 1);
          i--;
        }
      }
    }
    function removeCommonRoots(stacks) {
      var current = stacks[0];
      for (var i = 1; i < stacks.length; ++i) {
        var prev = stacks[i];
        var currentLastIndex = current.length - 1;
        var currentLastLine = current[currentLastIndex];
        var commonRootMeetPoint = -1;
        for (var j = prev.length - 1; j >= 0; --j) {
          if (prev[j] === currentLastLine) {
            commonRootMeetPoint = j;
            break;
          }
        }
        for (var j = commonRootMeetPoint; j >= 0; --j) {
          var line = prev[j];
          if (current[currentLastIndex] === line) {
            current.pop();
            currentLastIndex--;
          } else {
            break;
          }
        }
        current = prev;
      }
    }
    function cleanStack(stack) {
      var ret = [];
      for (var i = 0; i < stack.length; ++i) {
        var line = stack[i];
        var isTraceLine = "    (No stack trace)" === line || stackFramePattern.test(line);
        var isInternalFrame = isTraceLine && shouldIgnore(line);
        if (isTraceLine && !isInternalFrame) {
          if (indentStackFrames && line.charAt(0) !== " ") {
            line = "    " + line;
          }
          ret.push(line);
        }
      }
      return ret;
    }
    function stackFramesAsArray(error) {
      var stack = error.stack.replace(/\s+$/g, "").split("\n");
      for (var i = 0; i < stack.length; ++i) {
        var line = stack[i];
        if ("    (No stack trace)" === line || stackFramePattern.test(line)) {
          break;
        }
      }
      if (i > 0) {
        stack = stack.slice(i);
      }
      return stack;
    }
    function parseStackAndMessage(error) {
      var stack = error.stack;
      var message = error.toString();
      stack = typeof stack === "string" && stack.length > 0 ? stackFramesAsArray(error) : ["    (No stack trace)"];
      return {
        message: message,
        stack: cleanStack(stack)
      };
    }
    function formatAndLogError(error, title, isSoft) {
      if (typeof console !== "undefined") {
        var message;
        if (util.isObject(error)) {
          var stack = error.stack;
          message = title + formatStack(stack, error);
        } else {
          message = title + String(error);
        }
        if (typeof printWarning === "function") {
          printWarning(message, isSoft);
        } else if (typeof console.log === "function" || typeof console.log === "object") {
          console.log(message);
        }
      }
    }
    function fireRejectionEvent(name, localHandler, reason, promise) {
      var localEventFired = false;
      try {
        if (typeof localHandler === "function") {
          localEventFired = true;
          if (name === "rejectionHandled") {
            localHandler(promise);
          } else {
            localHandler(reason, promise);
          }
        }
      } catch (e) {
        async.throwLater(e);
      }
      if (name === "unhandledRejection") {
        if (!activeFireEvent(name, reason, promise) && !localEventFired) {
          formatAndLogError(reason, "Unhandled rejection ");
        }
      } else {
        activeFireEvent(name, promise);
      }
    }
    function formatNonError(obj) {
      var str;
      if (typeof obj === "function") {
        str = "[function " + (obj.name || "anonymous") + "]";
      } else {
        str = obj && typeof obj.toString === "function" ? obj.toString() : util.toString(obj);
        var ruselessToString = /\[object [a-zA-Z0-9$_]+\]/;
        if (ruselessToString.test(str)) {
          try {
            var newStr = JSON.stringify(obj);
            str = newStr;
          } catch (e) {}
        }
        if (str.length === 0) {
          str = "(empty array)";
        }
      }
      return ("(<" + snip(str) + ">, no stack trace)");
    }
    function snip(str) {
      var maxChars = 41;
      if (str.length < maxChars) {
        return str;
      }
      return str.substr(0, maxChars - 3) + "...";
    }
    function longStackTracesIsSupported() {
      return typeof captureStackTrace === "function";
    }
    var shouldIgnore = function() {
      return false;
    };
    var parseLineInfoRegex = /[\/<\(]([^:\/]+):(\d+):(?:\d+)\)?\s*$/;
    function parseLineInfo(line) {
      var matches = line.match(parseLineInfoRegex);
      if (matches) {
        return {
          fileName: matches[1],
          line: parseInt(matches[2], 10)
        };
      }
    }
    function setBounds(firstLineError, lastLineError) {
      if (!longStackTracesIsSupported())
        return;
      var firstStackLines = firstLineError.stack.split("\n");
      var lastStackLines = lastLineError.stack.split("\n");
      var firstIndex = -1;
      var lastIndex = -1;
      var firstFileName;
      var lastFileName;
      for (var i = 0; i < firstStackLines.length; ++i) {
        var result = parseLineInfo(firstStackLines[i]);
        if (result) {
          firstFileName = result.fileName;
          firstIndex = result.line;
          break;
        }
      }
      for (var i = 0; i < lastStackLines.length; ++i) {
        var result = parseLineInfo(lastStackLines[i]);
        if (result) {
          lastFileName = result.fileName;
          lastIndex = result.line;
          break;
        }
      }
      if (firstIndex < 0 || lastIndex < 0 || !firstFileName || !lastFileName || firstFileName !== lastFileName || firstIndex >= lastIndex) {
        return;
      }
      shouldIgnore = function(line) {
        if (bluebirdFramePattern.test(line))
          return true;
        var info = parseLineInfo(line);
        if (info) {
          if (info.fileName === firstFileName && (firstIndex <= info.line && info.line <= lastIndex)) {
            return true;
          }
        }
        return false;
      };
    }
    function CapturedTrace(parent) {
      this._parent = parent;
      this._promisesCreated = 0;
      var length = this._length = 1 + (parent === undefined ? 0 : parent._length);
      captureStackTrace(this, CapturedTrace);
      if (length > 32)
        this.uncycle();
    }
    util.inherits(CapturedTrace, Error);
    Context.CapturedTrace = CapturedTrace;
    CapturedTrace.prototype.uncycle = function() {
      var length = this._length;
      if (length < 2)
        return;
      var nodes = [];
      var stackToIndex = {};
      for (var i = 0,
          node = this; node !== undefined; ++i) {
        nodes.push(node);
        node = node._parent;
      }
      length = this._length = i;
      for (var i = length - 1; i >= 0; --i) {
        var stack = nodes[i].stack;
        if (stackToIndex[stack] === undefined) {
          stackToIndex[stack] = i;
        }
      }
      for (var i = 0; i < length; ++i) {
        var currentStack = nodes[i].stack;
        var index = stackToIndex[currentStack];
        if (index !== undefined && index !== i) {
          if (index > 0) {
            nodes[index - 1]._parent = undefined;
            nodes[index - 1]._length = 1;
          }
          nodes[i]._parent = undefined;
          nodes[i]._length = 1;
          var cycleEdgeNode = i > 0 ? nodes[i - 1] : this;
          if (index < length - 1) {
            cycleEdgeNode._parent = nodes[index + 1];
            cycleEdgeNode._parent.uncycle();
            cycleEdgeNode._length = cycleEdgeNode._parent._length + 1;
          } else {
            cycleEdgeNode._parent = undefined;
            cycleEdgeNode._length = 1;
          }
          var currentChildLength = cycleEdgeNode._length + 1;
          for (var j = i - 2; j >= 0; --j) {
            nodes[j]._length = currentChildLength;
            currentChildLength++;
          }
          return;
        }
      }
    };
    CapturedTrace.prototype.attachExtraTrace = function(error) {
      if (error.__stackCleaned__)
        return;
      this.uncycle();
      var parsed = parseStackAndMessage(error);
      var message = parsed.message;
      var stacks = [parsed.stack];
      var trace = this;
      while (trace !== undefined) {
        stacks.push(cleanStack(trace.stack.split("\n")));
        trace = trace._parent;
      }
      removeCommonRoots(stacks);
      removeDuplicateOrEmptyJumps(stacks);
      util.notEnumerableProp(error, "stack", reconstructStack(message, stacks));
      util.notEnumerableProp(error, "__stackCleaned__", true);
    };
    var captureStackTrace = (function stackDetection() {
      var v8stackFramePattern = /^\s*at\s*/;
      var v8stackFormatter = function(stack, error) {
        if (typeof stack === "string")
          return stack;
        if (error.name !== undefined && error.message !== undefined) {
          return error.toString();
        }
        return formatNonError(error);
      };
      if (typeof Error.stackTraceLimit === "number" && typeof Error.captureStackTrace === "function") {
        Error.stackTraceLimit += 6;
        stackFramePattern = v8stackFramePattern;
        formatStack = v8stackFormatter;
        var captureStackTrace = Error.captureStackTrace;
        shouldIgnore = function(line) {
          return bluebirdFramePattern.test(line);
        };
        return function(receiver, ignoreUntil) {
          Error.stackTraceLimit += 6;
          captureStackTrace(receiver, ignoreUntil);
          Error.stackTraceLimit -= 6;
        };
      }
      var err = new Error();
      if (typeof err.stack === "string" && err.stack.split("\n")[0].indexOf("stackDetection@") >= 0) {
        stackFramePattern = /@/;
        formatStack = v8stackFormatter;
        indentStackFrames = true;
        return function captureStackTrace(o) {
          o.stack = new Error().stack;
        };
      }
      var hasStackAfterThrow;
      try {
        throw new Error();
      } catch (e) {
        hasStackAfterThrow = ("stack" in e);
      }
      if (!("stack" in err) && hasStackAfterThrow && typeof Error.stackTraceLimit === "number") {
        stackFramePattern = v8stackFramePattern;
        formatStack = v8stackFormatter;
        return function captureStackTrace(o) {
          Error.stackTraceLimit += 6;
          try {
            throw new Error();
          } catch (e) {
            o.stack = e.stack;
          }
          Error.stackTraceLimit -= 6;
        };
      }
      formatStack = function(stack, error) {
        if (typeof stack === "string")
          return stack;
        if ((typeof error === "object" || typeof error === "function") && error.name !== undefined && error.message !== undefined) {
          return error.toString();
        }
        return formatNonError(error);
      };
      return null;
    })([]);
    if (typeof console !== "undefined" && typeof console.warn !== "undefined") {
      printWarning = function(message) {
        console.warn(message);
      };
      if (util.isNode && process.stderr.isTTY) {
        printWarning = function(message, isSoft) {
          var color = isSoft ? "\u001b[33m" : "\u001b[31m";
          console.warn(color + message + "\u001b[0m\n");
        };
      } else if (!util.isNode && typeof(new Error().stack) === "string") {
        printWarning = function(message, isSoft) {
          console.warn("%c" + message, isSoft ? "color: darkorange" : "color: red");
        };
      }
    }
    var config = {
      warnings: warnings,
      longStackTraces: false,
      cancellation: false,
      monitoring: false
    };
    if (longStackTraces)
      Promise.longStackTraces();
    return {
      longStackTraces: function() {
        return config.longStackTraces;
      },
      warnings: function() {
        return config.warnings;
      },
      cancellation: function() {
        return config.cancellation;
      },
      monitoring: function() {
        return config.monitoring;
      },
      propagateFromFunction: function() {
        return propagateFromFunction;
      },
      boundValueFunction: function() {
        return boundValueFunction;
      },
      checkForgottenReturns: checkForgottenReturns,
      setBounds: setBounds,
      warn: warn,
      deprecated: deprecated,
      CapturedTrace: CapturedTrace,
      fireDomEvent: fireDomEvent,
      fireGlobalEvent: fireGlobalEvent
    };
  };
  return module.exports;
});

$__System.registerDynamic("49", ["41"], true, function($__require, exports, module) {
  "use strict";
  ;
  var define,
      global = this,
      GLOBAL = this;
  module.exports = function(Promise, tryConvertToPromise) {
    var util = $__require('41');
    var CancellationError = Promise.CancellationError;
    var errorObj = util.errorObj;
    function PassThroughHandlerContext(promise, type, handler) {
      this.promise = promise;
      this.type = type;
      this.handler = handler;
      this.called = false;
      this.cancelPromise = null;
    }
    PassThroughHandlerContext.prototype.isFinallyHandler = function() {
      return this.type === 0;
    };
    function FinallyHandlerCancelReaction(finallyHandler) {
      this.finallyHandler = finallyHandler;
    }
    FinallyHandlerCancelReaction.prototype._resultCancelled = function() {
      checkCancel(this.finallyHandler);
    };
    function checkCancel(ctx, reason) {
      if (ctx.cancelPromise != null) {
        if (arguments.length > 1) {
          ctx.cancelPromise._reject(reason);
        } else {
          ctx.cancelPromise._cancel();
        }
        ctx.cancelPromise = null;
        return true;
      }
      return false;
    }
    function succeed() {
      return finallyHandler.call(this, this.promise._target()._settledValue());
    }
    function fail(reason) {
      if (checkCancel(this, reason))
        return;
      errorObj.e = reason;
      return errorObj;
    }
    function finallyHandler(reasonOrValue) {
      var promise = this.promise;
      var handler = this.handler;
      if (!this.called) {
        this.called = true;
        var ret = this.isFinallyHandler() ? handler.call(promise._boundValue()) : handler.call(promise._boundValue(), reasonOrValue);
        if (ret !== undefined) {
          promise._setReturnedNonUndefined();
          var maybePromise = tryConvertToPromise(ret, promise);
          if (maybePromise instanceof Promise) {
            if (this.cancelPromise != null) {
              if (maybePromise.isCancelled()) {
                var reason = new CancellationError("late cancellation observer");
                promise._attachExtraTrace(reason);
                errorObj.e = reason;
                return errorObj;
              } else if (maybePromise.isPending()) {
                maybePromise._attachCancellationCallback(new FinallyHandlerCancelReaction(this));
              }
            }
            return maybePromise._then(succeed, fail, undefined, this, undefined);
          }
        }
      }
      if (promise.isRejected()) {
        checkCancel(this);
        errorObj.e = reasonOrValue;
        return errorObj;
      } else {
        checkCancel(this);
        return reasonOrValue;
      }
    }
    Promise.prototype._passThrough = function(handler, type, success, fail) {
      if (typeof handler !== "function")
        return this.then();
      return this._then(success, fail, undefined, new PassThroughHandlerContext(this, type, handler), undefined);
    };
    Promise.prototype.lastly = Promise.prototype["finally"] = function(handler) {
      return this._passThrough(handler, 0, finallyHandler, finallyHandler);
    };
    Promise.prototype.tap = function(handler) {
      return this._passThrough(handler, 1, finallyHandler);
    };
    return PassThroughHandlerContext;
  };
  return module.exports;
});

$__System.registerDynamic("4a", ["41", "4b"], true, function($__require, exports, module) {
  "use strict";
  ;
  var define,
      global = this,
      GLOBAL = this;
  module.exports = function(NEXT_FILTER) {
    var util = $__require('41');
    var getKeys = $__require('4b').keys;
    var tryCatch = util.tryCatch;
    var errorObj = util.errorObj;
    function catchFilter(instances, cb, promise) {
      return function(e) {
        var boundTo = promise._boundValue();
        predicateLoop: for (var i = 0; i < instances.length; ++i) {
          var item = instances[i];
          if (item === Error || (item != null && item.prototype instanceof Error)) {
            if (e instanceof item) {
              return tryCatch(cb).call(boundTo, e);
            }
          } else if (typeof item === "function") {
            var matchesPredicate = tryCatch(item).call(boundTo, e);
            if (matchesPredicate === errorObj) {
              return matchesPredicate;
            } else if (matchesPredicate) {
              return tryCatch(cb).call(boundTo, e);
            }
          } else if (util.isObject(e)) {
            var keys = getKeys(item);
            for (var j = 0; j < keys.length; ++j) {
              var key = keys[j];
              if (item[key] != e[key]) {
                continue predicateLoop;
              }
            }
            return tryCatch(cb).call(boundTo, e);
          }
        }
        return NEXT_FILTER;
      };
    }
    return catchFilter;
  };
  return module.exports;
});

$__System.registerDynamic("4c", ["41"], true, function($__require, exports, module) {
  "use strict";
  ;
  var define,
      global = this,
      GLOBAL = this;
  module.exports = function(Promise, INTERNAL, tryConvertToPromise, apiRejection, debug) {
    var util = $__require('41');
    var tryCatch = util.tryCatch;
    Promise.method = function(fn) {
      if (typeof fn !== "function") {
        throw new Promise.TypeError("expecting a function but got " + util.classString(fn));
      }
      return function() {
        var ret = new Promise(INTERNAL);
        ret._captureStackTrace();
        ret._pushContext();
        var value = tryCatch(fn).apply(this, arguments);
        var promiseCreated = ret._popContext();
        debug.checkForgottenReturns(value, promiseCreated, "Promise.method", ret);
        ret._resolveFromSyncValue(value);
        return ret;
      };
    };
    Promise.attempt = Promise["try"] = function(fn) {
      if (typeof fn !== "function") {
        return apiRejection("expecting a function but got " + util.classString(fn));
      }
      var ret = new Promise(INTERNAL);
      ret._captureStackTrace();
      ret._pushContext();
      var value;
      if (arguments.length > 1) {
        debug.deprecated("calling Promise.try with more than 1 argument");
        var arg = arguments[1];
        var ctx = arguments[2];
        value = util.isArray(arg) ? tryCatch(fn).apply(ctx, arg) : tryCatch(fn).call(ctx, arg);
      } else {
        value = tryCatch(fn)();
      }
      var promiseCreated = ret._popContext();
      debug.checkForgottenReturns(value, promiseCreated, "Promise.try", ret);
      ret._resolveFromSyncValue(value);
      return ret;
    };
    Promise.prototype._resolveFromSyncValue = function(value) {
      if (value === util.errorObj) {
        this._rejectCallback(value.e, false);
      } else {
        this._resolveCallback(value, true);
      }
    };
  };
  return module.exports;
});

$__System.registerDynamic("4d", [], true, function($__require, exports, module) {
  "use strict";
  ;
  var define,
      global = this,
      GLOBAL = this;
  module.exports = function(Promise, INTERNAL, tryConvertToPromise, debug) {
    var calledBind = false;
    var rejectThis = function(_, e) {
      this._reject(e);
    };
    var targetRejected = function(e, context) {
      context.promiseRejectionQueued = true;
      context.bindingPromise._then(rejectThis, rejectThis, null, this, e);
    };
    var bindingResolved = function(thisArg, context) {
      if (((this._bitField & 50397184) === 0)) {
        this._resolveCallback(context.target);
      }
    };
    var bindingRejected = function(e, context) {
      if (!context.promiseRejectionQueued)
        this._reject(e);
    };
    Promise.prototype.bind = function(thisArg) {
      if (!calledBind) {
        calledBind = true;
        Promise.prototype._propagateFrom = debug.propagateFromFunction();
        Promise.prototype._boundValue = debug.boundValueFunction();
      }
      var maybePromise = tryConvertToPromise(thisArg);
      var ret = new Promise(INTERNAL);
      ret._propagateFrom(this, 1);
      var target = this._target();
      ret._setBoundTo(maybePromise);
      if (maybePromise instanceof Promise) {
        var context = {
          promiseRejectionQueued: false,
          promise: ret,
          target: target,
          bindingPromise: maybePromise
        };
        target._then(INTERNAL, targetRejected, undefined, ret, context);
        maybePromise._then(bindingResolved, bindingRejected, undefined, ret, context);
        ret._setOnCancel(maybePromise);
      } else {
        ret._resolveCallback(target);
      }
      return ret;
    };
    Promise.prototype._setBoundTo = function(obj) {
      if (obj !== undefined) {
        this._bitField = this._bitField | 2097152;
        this._boundTo = obj;
      } else {
        this._bitField = this._bitField & (~2097152);
      }
    };
    Promise.prototype._isBound = function() {
      return (this._bitField & 2097152) === 2097152;
    };
    Promise.bind = function(thisArg, value) {
      return Promise.resolve(value).bind(thisArg);
    };
  };
  return module.exports;
});

$__System.registerDynamic("4e", ["41"], true, function($__require, exports, module) {
  "use strict";
  ;
  var define,
      global = this,
      GLOBAL = this;
  module.exports = function(Promise, PromiseArray, apiRejection, debug) {
    var util = $__require('41');
    var tryCatch = util.tryCatch;
    var errorObj = util.errorObj;
    var async = Promise._async;
    Promise.prototype["break"] = Promise.prototype.cancel = function() {
      if (!debug.cancellation())
        return this._warn("cancellation is disabled");
      var promise = this;
      var child = promise;
      while (promise.isCancellable()) {
        if (!promise._cancelBy(child)) {
          if (child._isFollowing()) {
            child._followee().cancel();
          } else {
            child._cancelBranched();
          }
          break;
        }
        var parent = promise._cancellationParent;
        if (parent == null || !parent.isCancellable()) {
          if (promise._isFollowing()) {
            promise._followee().cancel();
          } else {
            promise._cancelBranched();
          }
          break;
        } else {
          if (promise._isFollowing())
            promise._followee().cancel();
          child = promise;
          promise = parent;
        }
      }
    };
    Promise.prototype._branchHasCancelled = function() {
      this._branchesRemainingToCancel--;
    };
    Promise.prototype._enoughBranchesHaveCancelled = function() {
      return this._branchesRemainingToCancel === undefined || this._branchesRemainingToCancel <= 0;
    };
    Promise.prototype._cancelBy = function(canceller) {
      if (canceller === this) {
        this._branchesRemainingToCancel = 0;
        this._invokeOnCancel();
        return true;
      } else {
        this._branchHasCancelled();
        if (this._enoughBranchesHaveCancelled()) {
          this._invokeOnCancel();
          return true;
        }
      }
      return false;
    };
    Promise.prototype._cancelBranched = function() {
      if (this._enoughBranchesHaveCancelled()) {
        this._cancel();
      }
    };
    Promise.prototype._cancel = function() {
      if (!this.isCancellable())
        return;
      this._setCancelled();
      async.invoke(this._cancelPromises, this, undefined);
    };
    Promise.prototype._cancelPromises = function() {
      if (this._length() > 0)
        this._settlePromises();
    };
    Promise.prototype._unsetOnCancel = function() {
      this._onCancelField = undefined;
    };
    Promise.prototype.isCancellable = function() {
      return this.isPending() && !this.isCancelled();
    };
    Promise.prototype._doInvokeOnCancel = function(onCancelCallback, internalOnly) {
      if (util.isArray(onCancelCallback)) {
        for (var i = 0; i < onCancelCallback.length; ++i) {
          this._doInvokeOnCancel(onCancelCallback[i], internalOnly);
        }
      } else if (onCancelCallback !== undefined) {
        if (typeof onCancelCallback === "function") {
          if (!internalOnly) {
            var e = tryCatch(onCancelCallback).call(this._boundValue());
            if (e === errorObj) {
              this._attachExtraTrace(e.e);
              async.throwLater(e.e);
            }
          }
        } else {
          onCancelCallback._resultCancelled(this);
        }
      }
    };
    Promise.prototype._invokeOnCancel = function() {
      var onCancelCallback = this._onCancel();
      this._unsetOnCancel();
      async.invoke(this._doInvokeOnCancel, this, onCancelCallback);
    };
    Promise.prototype._invokeInternalOnCancel = function() {
      if (this.isCancellable()) {
        this._doInvokeOnCancel(this._onCancel(), true);
        this._unsetOnCancel();
      }
    };
    Promise.prototype._resultCancelled = function() {
      this.cancel();
    };
  };
  return module.exports;
});

$__System.registerDynamic("4f", [], true, function($__require, exports, module) {
  "use strict";
  ;
  var define,
      global = this,
      GLOBAL = this;
  module.exports = function(Promise) {
    function returner() {
      return this.value;
    }
    function thrower() {
      throw this.reason;
    }
    Promise.prototype["return"] = Promise.prototype.thenReturn = function(value) {
      if (value instanceof Promise)
        value.suppressUnhandledRejections();
      return this._then(returner, undefined, undefined, {value: value}, undefined);
    };
    Promise.prototype["throw"] = Promise.prototype.thenThrow = function(reason) {
      return this._then(thrower, undefined, undefined, {reason: reason}, undefined);
    };
    Promise.prototype.catchThrow = function(reason) {
      if (arguments.length <= 1) {
        return this._then(undefined, thrower, undefined, {reason: reason}, undefined);
      } else {
        var _reason = arguments[1];
        var handler = function() {
          throw _reason;
        };
        return this.caught(reason, handler);
      }
    };
    Promise.prototype.catchReturn = function(value) {
      if (arguments.length <= 1) {
        if (value instanceof Promise)
          value.suppressUnhandledRejections();
        return this._then(undefined, returner, undefined, {value: value}, undefined);
      } else {
        var _value = arguments[1];
        if (_value instanceof Promise)
          _value.suppressUnhandledRejections();
        var handler = function() {
          return _value;
        };
        return this.caught(value, handler);
      }
    };
  };
  return module.exports;
});

$__System.registerDynamic("50", [], true, function($__require, exports, module) {
  "use strict";
  ;
  var define,
      global = this,
      GLOBAL = this;
  module.exports = function(Promise) {
    function PromiseInspection(promise) {
      if (promise !== undefined) {
        promise = promise._target();
        this._bitField = promise._bitField;
        this._settledValueField = promise._isFateSealed() ? promise._settledValue() : undefined;
      } else {
        this._bitField = 0;
        this._settledValueField = undefined;
      }
    }
    PromiseInspection.prototype._settledValue = function() {
      return this._settledValueField;
    };
    var value = PromiseInspection.prototype.value = function() {
      if (!this.isFulfilled()) {
        throw new TypeError("cannot get fulfillment value of a non-fulfilled promise\u000a\u000a    See http://goo.gl/MqrFmX\u000a");
      }
      return this._settledValue();
    };
    var reason = PromiseInspection.prototype.error = PromiseInspection.prototype.reason = function() {
      if (!this.isRejected()) {
        throw new TypeError("cannot get rejection reason of a non-rejected promise\u000a\u000a    See http://goo.gl/MqrFmX\u000a");
      }
      return this._settledValue();
    };
    var isFulfilled = PromiseInspection.prototype.isFulfilled = function() {
      return (this._bitField & 33554432) !== 0;
    };
    var isRejected = PromiseInspection.prototype.isRejected = function() {
      return (this._bitField & 16777216) !== 0;
    };
    var isPending = PromiseInspection.prototype.isPending = function() {
      return (this._bitField & 50397184) === 0;
    };
    var isResolved = PromiseInspection.prototype.isResolved = function() {
      return (this._bitField & 50331648) !== 0;
    };
    PromiseInspection.prototype.isCancelled = Promise.prototype._isCancelled = function() {
      return (this._bitField & 65536) === 65536;
    };
    Promise.prototype.isCancelled = function() {
      return this._target()._isCancelled();
    };
    Promise.prototype.isPending = function() {
      return isPending.call(this._target());
    };
    Promise.prototype.isRejected = function() {
      return isRejected.call(this._target());
    };
    Promise.prototype.isFulfilled = function() {
      return isFulfilled.call(this._target());
    };
    Promise.prototype.isResolved = function() {
      return isResolved.call(this._target());
    };
    Promise.prototype.value = function() {
      return value.call(this._target());
    };
    Promise.prototype.reason = function() {
      var target = this._target();
      target._unsetRejectionIsUnhandled();
      return reason.call(target);
    };
    Promise.prototype._value = function() {
      return this._settledValue();
    };
    Promise.prototype._reason = function() {
      this._unsetRejectionIsUnhandled();
      return this._settledValue();
    };
    Promise.PromiseInspection = PromiseInspection;
  };
  return module.exports;
});

$__System.registerDynamic("51", ["41"], true, function($__require, exports, module) {
  "use strict";
  ;
  var define,
      global = this,
      GLOBAL = this;
  module.exports = function(Promise, PromiseArray, tryConvertToPromise, INTERNAL) {
    var util = $__require('41');
    var canEvaluate = util.canEvaluate;
    var tryCatch = util.tryCatch;
    var errorObj = util.errorObj;
    var reject;
    if (!false) {
      if (canEvaluate) {
        var thenCallback = function(i) {
          return new Function("value", "holder", "                             \n\
            'use strict';                                                    \n\
            holder.pIndex = value;                                           \n\
            holder.checkFulfillment(this);                                   \n\
            ".replace(/Index/g, i));
        };
        var promiseSetter = function(i) {
          return new Function("promise", "holder", "                           \n\
            'use strict';                                                    \n\
            holder.pIndex = promise;                                         \n\
            ".replace(/Index/g, i));
        };
        var generateHolderClass = function(total) {
          var props = new Array(total);
          for (var i = 0; i < props.length; ++i) {
            props[i] = "this.p" + (i + 1);
          }
          var assignment = props.join(" = ") + " = null;";
          var cancellationCode = "var promise;\n" + props.map(function(prop) {
            return "                                                         \n\
                promise = " + prop + ";                                      \n\
                if (promise instanceof Promise) {                            \n\
                    promise.cancel();                                        \n\
                }                                                            \n\
            ";
          }).join("\n");
          var passedArguments = props.join(", ");
          var name = "Holder$" + total;
          var code = "return function(tryCatch, errorObj, Promise) {           \n\
            'use strict';                                                    \n\
            function [TheName](fn) {                                         \n\
                [TheProperties]                                              \n\
                this.fn = fn;                                                \n\
                this.now = 0;                                                \n\
            }                                                                \n\
            [TheName].prototype.checkFulfillment = function(promise) {       \n\
                var now = ++this.now;                                        \n\
                if (now === [TheTotal]) {                                    \n\
                    promise._pushContext();                                  \n\
                    var callback = this.fn;                                  \n\
                    var ret = tryCatch(callback)([ThePassedArguments]);      \n\
                    promise._popContext();                                   \n\
                    if (ret === errorObj) {                                  \n\
                        promise._rejectCallback(ret.e, false);               \n\
                    } else {                                                 \n\
                        promise._resolveCallback(ret);                       \n\
                    }                                                        \n\
                }                                                            \n\
            };                                                               \n\
                                                                             \n\
            [TheName].prototype._resultCancelled = function() {              \n\
                [CancellationCode]                                           \n\
            };                                                               \n\
                                                                             \n\
            return [TheName];                                                \n\
        }(tryCatch, errorObj, Promise);                                      \n\
        ";
          code = code.replace(/\[TheName\]/g, name).replace(/\[TheTotal\]/g, total).replace(/\[ThePassedArguments\]/g, passedArguments).replace(/\[TheProperties\]/g, assignment).replace(/\[CancellationCode\]/g, cancellationCode);
          return new Function("tryCatch", "errorObj", "Promise", code)(tryCatch, errorObj, Promise);
        };
        var holderClasses = [];
        var thenCallbacks = [];
        var promiseSetters = [];
        for (var i = 0; i < 8; ++i) {
          holderClasses.push(generateHolderClass(i + 1));
          thenCallbacks.push(thenCallback(i + 1));
          promiseSetters.push(promiseSetter(i + 1));
        }
        reject = function(reason) {
          this._reject(reason);
        };
      }
    }
    Promise.join = function() {
      var last = arguments.length - 1;
      var fn;
      if (last > 0 && typeof arguments[last] === "function") {
        fn = arguments[last];
        if (!false) {
          if (last <= 8 && canEvaluate) {
            var ret = new Promise(INTERNAL);
            ret._captureStackTrace();
            var HolderClass = holderClasses[last - 1];
            var holder = new HolderClass(fn);
            var callbacks = thenCallbacks;
            for (var i = 0; i < last; ++i) {
              var maybePromise = tryConvertToPromise(arguments[i], ret);
              if (maybePromise instanceof Promise) {
                maybePromise = maybePromise._target();
                var bitField = maybePromise._bitField;
                ;
                if (((bitField & 50397184) === 0)) {
                  maybePromise._then(callbacks[i], reject, undefined, ret, holder);
                  promiseSetters[i](maybePromise, holder);
                } else if (((bitField & 33554432) !== 0)) {
                  callbacks[i].call(ret, maybePromise._value(), holder);
                } else if (((bitField & 16777216) !== 0)) {
                  ret._reject(maybePromise._reason());
                } else {
                  ret._cancel();
                }
              } else {
                callbacks[i].call(ret, maybePromise, holder);
              }
            }
            if (!ret._isFateSealed()) {
              ret._setAsyncGuaranteed();
              ret._setOnCancel(holder);
            }
            return ret;
          }
        }
      }
      var $_len = arguments.length;
      var args = new Array($_len);
      for (var $_i = 0; $_i < $_len; ++$_i) {
        args[$_i] = arguments[$_i];
      }
      ;
      if (fn)
        args.pop();
      var ret = new PromiseArray(args).promise();
      return fn !== undefined ? ret.spread(fn) : ret;
    };
  };
  return module.exports;
});

$__System.registerDynamic("52", ["41"], true, function($__require, exports, module) {
  "use strict";
  ;
  var define,
      global = this,
      GLOBAL = this;
  module.exports = function(Promise, PromiseArray, apiRejection, tryConvertToPromise, INTERNAL, debug) {
    var getDomain = Promise._getDomain;
    var util = $__require('41');
    var tryCatch = util.tryCatch;
    var errorObj = util.errorObj;
    var EMPTY_ARRAY = [];
    function MappingPromiseArray(promises, fn, limit, _filter) {
      this.constructor$(promises);
      this._promise._captureStackTrace();
      var domain = getDomain();
      this._callback = domain === null ? fn : domain.bind(fn);
      this._preservedValues = _filter === INTERNAL ? new Array(this.length()) : null;
      this._limit = limit;
      this._inFlight = 0;
      this._queue = limit >= 1 ? [] : EMPTY_ARRAY;
      this._init$(undefined, -2);
    }
    util.inherits(MappingPromiseArray, PromiseArray);
    MappingPromiseArray.prototype._init = function() {};
    MappingPromiseArray.prototype._promiseFulfilled = function(value, index) {
      var values = this._values;
      var length = this.length();
      var preservedValues = this._preservedValues;
      var limit = this._limit;
      if (index < 0) {
        index = (index * -1) - 1;
        values[index] = value;
        if (limit >= 1) {
          this._inFlight--;
          this._drainQueue();
          if (this._isResolved())
            return true;
        }
      } else {
        if (limit >= 1 && this._inFlight >= limit) {
          values[index] = value;
          this._queue.push(index);
          return false;
        }
        if (preservedValues !== null)
          preservedValues[index] = value;
        var promise = this._promise;
        var callback = this._callback;
        var receiver = promise._boundValue();
        promise._pushContext();
        var ret = tryCatch(callback).call(receiver, value, index, length);
        var promiseCreated = promise._popContext();
        debug.checkForgottenReturns(ret, promiseCreated, preservedValues !== null ? "Promise.filter" : "Promise.map", promise);
        if (ret === errorObj) {
          this._reject(ret.e);
          return true;
        }
        var maybePromise = tryConvertToPromise(ret, this._promise);
        if (maybePromise instanceof Promise) {
          maybePromise = maybePromise._target();
          var bitField = maybePromise._bitField;
          ;
          if (((bitField & 50397184) === 0)) {
            if (limit >= 1)
              this._inFlight++;
            values[index] = maybePromise;
            maybePromise._proxy(this, (index + 1) * -1);
            return false;
          } else if (((bitField & 33554432) !== 0)) {
            ret = maybePromise._value();
          } else if (((bitField & 16777216) !== 0)) {
            this._reject(maybePromise._reason());
            return true;
          } else {
            this._cancel();
            return true;
          }
        }
        values[index] = ret;
      }
      var totalResolved = ++this._totalResolved;
      if (totalResolved >= length) {
        if (preservedValues !== null) {
          this._filter(values, preservedValues);
        } else {
          this._resolve(values);
        }
        return true;
      }
      return false;
    };
    MappingPromiseArray.prototype._drainQueue = function() {
      var queue = this._queue;
      var limit = this._limit;
      var values = this._values;
      while (queue.length > 0 && this._inFlight < limit) {
        if (this._isResolved())
          return;
        var index = queue.pop();
        this._promiseFulfilled(values[index], index);
      }
    };
    MappingPromiseArray.prototype._filter = function(booleans, values) {
      var len = values.length;
      var ret = new Array(len);
      var j = 0;
      for (var i = 0; i < len; ++i) {
        if (booleans[i])
          ret[j++] = values[i];
      }
      ret.length = j;
      this._resolve(ret);
    };
    MappingPromiseArray.prototype.preservedValues = function() {
      return this._preservedValues;
    };
    function map(promises, fn, options, _filter) {
      if (typeof fn !== "function") {
        return apiRejection("expecting a function but got " + util.classString(fn));
      }
      var limit = typeof options === "object" && options !== null ? options.concurrency : 0;
      limit = typeof limit === "number" && isFinite(limit) && limit >= 1 ? limit : 0;
      return new MappingPromiseArray(promises, fn, limit, _filter).promise();
    }
    Promise.prototype.map = function(fn, options) {
      return map(this, fn, options, null);
    };
    Promise.map = function(promises, fn, options, _filter) {
      return map(promises, fn, options, _filter);
    };
  };
  return module.exports;
});

$__System.registerDynamic("53", ["41", "48"], true, function($__require, exports, module) {
  "use strict";
  ;
  var define,
      global = this,
      GLOBAL = this;
  module.exports = function(Promise, apiRejection, tryConvertToPromise, createContext, INTERNAL, debug) {
    var util = $__require('41');
    var TypeError = $__require('48').TypeError;
    var inherits = $__require('41').inherits;
    var errorObj = util.errorObj;
    var tryCatch = util.tryCatch;
    function thrower(e) {
      setTimeout(function() {
        throw e;
      }, 0);
    }
    function castPreservingDisposable(thenable) {
      var maybePromise = tryConvertToPromise(thenable);
      if (maybePromise !== thenable && typeof thenable._isDisposable === "function" && typeof thenable._getDisposer === "function" && thenable._isDisposable()) {
        maybePromise._setDisposable(thenable._getDisposer());
      }
      return maybePromise;
    }
    function dispose(resources, inspection) {
      var i = 0;
      var len = resources.length;
      var ret = new Promise(INTERNAL);
      function iterator() {
        if (i >= len)
          return ret._fulfill();
        var maybePromise = castPreservingDisposable(resources[i++]);
        if (maybePromise instanceof Promise && maybePromise._isDisposable()) {
          try {
            maybePromise = tryConvertToPromise(maybePromise._getDisposer().tryDispose(inspection), resources.promise);
          } catch (e) {
            return thrower(e);
          }
          if (maybePromise instanceof Promise) {
            return maybePromise._then(iterator, thrower, null, null, null);
          }
        }
        iterator();
      }
      iterator();
      return ret;
    }
    function Disposer(data, promise, context) {
      this._data = data;
      this._promise = promise;
      this._context = context;
    }
    Disposer.prototype.data = function() {
      return this._data;
    };
    Disposer.prototype.promise = function() {
      return this._promise;
    };
    Disposer.prototype.resource = function() {
      if (this.promise().isFulfilled()) {
        return this.promise().value();
      }
      return null;
    };
    Disposer.prototype.tryDispose = function(inspection) {
      var resource = this.resource();
      var context = this._context;
      if (context !== undefined)
        context._pushContext();
      var ret = resource !== null ? this.doDispose(resource, inspection) : null;
      if (context !== undefined)
        context._popContext();
      this._promise._unsetDisposable();
      this._data = null;
      return ret;
    };
    Disposer.isDisposer = function(d) {
      return (d != null && typeof d.resource === "function" && typeof d.tryDispose === "function");
    };
    function FunctionDisposer(fn, promise, context) {
      this.constructor$(fn, promise, context);
    }
    inherits(FunctionDisposer, Disposer);
    FunctionDisposer.prototype.doDispose = function(resource, inspection) {
      var fn = this.data();
      return fn.call(resource, resource, inspection);
    };
    function maybeUnwrapDisposer(value) {
      if (Disposer.isDisposer(value)) {
        this.resources[this.index]._setDisposable(value);
        return value.promise();
      }
      return value;
    }
    function ResourceList(length) {
      this.length = length;
      this.promise = null;
      this[length - 1] = null;
    }
    ResourceList.prototype._resultCancelled = function() {
      var len = this.length;
      for (var i = 0; i < len; ++i) {
        var item = this[i];
        if (item instanceof Promise) {
          item.cancel();
        }
      }
    };
    Promise.using = function() {
      var len = arguments.length;
      if (len < 2)
        return apiRejection("you must pass at least 2 arguments to Promise.using");
      var fn = arguments[len - 1];
      if (typeof fn !== "function") {
        return apiRejection("expecting a function but got " + util.classString(fn));
      }
      var input;
      var spreadArgs = true;
      if (len === 2 && Array.isArray(arguments[0])) {
        input = arguments[0];
        len = input.length;
        spreadArgs = false;
      } else {
        input = arguments;
        len--;
      }
      var resources = new ResourceList(len);
      for (var i = 0; i < len; ++i) {
        var resource = input[i];
        if (Disposer.isDisposer(resource)) {
          var disposer = resource;
          resource = resource.promise();
          resource._setDisposable(disposer);
        } else {
          var maybePromise = tryConvertToPromise(resource);
          if (maybePromise instanceof Promise) {
            resource = maybePromise._then(maybeUnwrapDisposer, null, null, {
              resources: resources,
              index: i
            }, undefined);
          }
        }
        resources[i] = resource;
      }
      var reflectedResources = new Array(resources.length);
      for (var i = 0; i < reflectedResources.length; ++i) {
        reflectedResources[i] = Promise.resolve(resources[i]).reflect();
      }
      var resultPromise = Promise.all(reflectedResources).then(function(inspections) {
        for (var i = 0; i < inspections.length; ++i) {
          var inspection = inspections[i];
          if (inspection.isRejected()) {
            errorObj.e = inspection.error();
            return errorObj;
          } else if (!inspection.isFulfilled()) {
            resultPromise.cancel();
            return;
          }
          inspections[i] = inspection.value();
        }
        promise._pushContext();
        fn = tryCatch(fn);
        var ret = spreadArgs ? fn.apply(undefined, inspections) : fn(inspections);
        var promiseCreated = promise._popContext();
        debug.checkForgottenReturns(ret, promiseCreated, "Promise.using", promise);
        return ret;
      });
      var promise = resultPromise.lastly(function() {
        var inspection = new Promise.PromiseInspection(resultPromise);
        return dispose(resources, inspection);
      });
      resources.promise = promise;
      promise._setOnCancel(resources);
      return promise;
    };
    Promise.prototype._setDisposable = function(disposer) {
      this._bitField = this._bitField | 131072;
      this._disposer = disposer;
    };
    Promise.prototype._isDisposable = function() {
      return (this._bitField & 131072) > 0;
    };
    Promise.prototype._getDisposer = function() {
      return this._disposer;
    };
    Promise.prototype._unsetDisposable = function() {
      this._bitField = this._bitField & (~131072);
      this._disposer = undefined;
    };
    Promise.prototype.disposer = function(fn) {
      if (typeof fn === "function") {
        return new FunctionDisposer(fn, this, createContext());
      }
      throw new TypeError();
    };
  };
  return module.exports;
});

$__System.registerDynamic("54", ["41"], true, function($__require, exports, module) {
  "use strict";
  ;
  var define,
      global = this,
      GLOBAL = this;
  module.exports = function(Promise, INTERNAL, debug) {
    var util = $__require('41');
    var TimeoutError = Promise.TimeoutError;
    function HandleWrapper(handle) {
      this.handle = handle;
    }
    HandleWrapper.prototype._resultCancelled = function() {
      clearTimeout(this.handle);
    };
    var afterValue = function(value) {
      return delay(+this).thenReturn(value);
    };
    var delay = Promise.delay = function(ms, value) {
      var ret;
      var handle;
      if (value !== undefined) {
        ret = Promise.resolve(value)._then(afterValue, null, null, ms, undefined);
        if (debug.cancellation() && value instanceof Promise) {
          ret._setOnCancel(value);
        }
      } else {
        ret = new Promise(INTERNAL);
        handle = setTimeout(function() {
          ret._fulfill();
        }, +ms);
        if (debug.cancellation()) {
          ret._setOnCancel(new HandleWrapper(handle));
        }
      }
      ret._setAsyncGuaranteed();
      return ret;
    };
    Promise.prototype.delay = function(ms) {
      return delay(ms, this);
    };
    var afterTimeout = function(promise, message, parent) {
      var err;
      if (typeof message !== "string") {
        if (message instanceof Error) {
          err = message;
        } else {
          err = new TimeoutError("operation timed out");
        }
      } else {
        err = new TimeoutError(message);
      }
      util.markAsOriginatingFromRejection(err);
      promise._attachExtraTrace(err);
      promise._reject(err);
      if (parent != null) {
        parent.cancel();
      }
    };
    function successClear(value) {
      clearTimeout(this.handle);
      return value;
    }
    function failureClear(reason) {
      clearTimeout(this.handle);
      throw reason;
    }
    Promise.prototype.timeout = function(ms, message) {
      ms = +ms;
      var ret,
          parent;
      var handleWrapper = new HandleWrapper(setTimeout(function timeoutTimeout() {
        if (ret.isPending()) {
          afterTimeout(ret, message, parent);
        }
      }, ms));
      if (debug.cancellation()) {
        parent = this.then();
        ret = parent._then(successClear, failureClear, undefined, handleWrapper, undefined);
        ret._setOnCancel(handleWrapper);
      } else {
        ret = this._then(successClear, failureClear, undefined, handleWrapper, undefined);
      }
      return ret;
    };
  };
  return module.exports;
});

$__System.registerDynamic("55", ["48", "41"], true, function($__require, exports, module) {
  "use strict";
  ;
  var define,
      global = this,
      GLOBAL = this;
  module.exports = function(Promise, apiRejection, INTERNAL, tryConvertToPromise, Proxyable, debug) {
    var errors = $__require('48');
    var TypeError = errors.TypeError;
    var util = $__require('41');
    var errorObj = util.errorObj;
    var tryCatch = util.tryCatch;
    var yieldHandlers = [];
    function promiseFromYieldHandler(value, yieldHandlers, traceParent) {
      for (var i = 0; i < yieldHandlers.length; ++i) {
        traceParent._pushContext();
        var result = tryCatch(yieldHandlers[i])(value);
        traceParent._popContext();
        if (result === errorObj) {
          traceParent._pushContext();
          var ret = Promise.reject(errorObj.e);
          traceParent._popContext();
          return ret;
        }
        var maybePromise = tryConvertToPromise(result, traceParent);
        if (maybePromise instanceof Promise)
          return maybePromise;
      }
      return null;
    }
    function PromiseSpawn(generatorFunction, receiver, yieldHandler, stack) {
      var promise = this._promise = new Promise(INTERNAL);
      promise._captureStackTrace();
      promise._setOnCancel(this);
      this._stack = stack;
      this._generatorFunction = generatorFunction;
      this._receiver = receiver;
      this._generator = undefined;
      this._yieldHandlers = typeof yieldHandler === "function" ? [yieldHandler].concat(yieldHandlers) : yieldHandlers;
      this._yieldedPromise = null;
    }
    util.inherits(PromiseSpawn, Proxyable);
    PromiseSpawn.prototype._isResolved = function() {
      return this._promise === null;
    };
    PromiseSpawn.prototype._cleanup = function() {
      this._promise = this._generator = null;
    };
    PromiseSpawn.prototype._promiseCancelled = function() {
      if (this._isResolved())
        return;
      var implementsReturn = typeof this._generator["return"] !== "undefined";
      var result;
      if (!implementsReturn) {
        var reason = new Promise.CancellationError("generator .return() sentinel");
        Promise.coroutine.returnSentinel = reason;
        this._promise._attachExtraTrace(reason);
        this._promise._pushContext();
        result = tryCatch(this._generator["throw"]).call(this._generator, reason);
        this._promise._popContext();
        if (result === errorObj && result.e === reason) {
          result = null;
        }
      } else {
        this._promise._pushContext();
        result = tryCatch(this._generator["return"]).call(this._generator, undefined);
        this._promise._popContext();
      }
      var promise = this._promise;
      this._cleanup();
      if (result === errorObj) {
        promise._rejectCallback(result.e, false);
      } else {
        promise.cancel();
      }
    };
    PromiseSpawn.prototype._promiseFulfilled = function(value) {
      this._yieldedPromise = null;
      this._promise._pushContext();
      var result = tryCatch(this._generator.next).call(this._generator, value);
      this._promise._popContext();
      this._continue(result);
    };
    PromiseSpawn.prototype._promiseRejected = function(reason) {
      this._yieldedPromise = null;
      this._promise._attachExtraTrace(reason);
      this._promise._pushContext();
      var result = tryCatch(this._generator["throw"]).call(this._generator, reason);
      this._promise._popContext();
      this._continue(result);
    };
    PromiseSpawn.prototype._resultCancelled = function() {
      if (this._yieldedPromise instanceof Promise) {
        var promise = this._yieldedPromise;
        this._yieldedPromise = null;
        this._promiseCancelled();
        promise.cancel();
      }
    };
    PromiseSpawn.prototype.promise = function() {
      return this._promise;
    };
    PromiseSpawn.prototype._run = function() {
      this._generator = this._generatorFunction.call(this._receiver);
      this._receiver = this._generatorFunction = undefined;
      this._promiseFulfilled(undefined);
    };
    PromiseSpawn.prototype._continue = function(result) {
      var promise = this._promise;
      if (result === errorObj) {
        this._cleanup();
        return promise._rejectCallback(result.e, false);
      }
      var value = result.value;
      if (result.done === true) {
        this._cleanup();
        return promise._resolveCallback(value);
      } else {
        var maybePromise = tryConvertToPromise(value, this._promise);
        if (!(maybePromise instanceof Promise)) {
          maybePromise = promiseFromYieldHandler(maybePromise, this._yieldHandlers, this._promise);
          if (maybePromise === null) {
            this._promiseRejected(new TypeError("A value %s was yielded that could not be treated as a promise\u000a\u000a    See http://goo.gl/MqrFmX\u000a\u000a".replace("%s", value) + "From coroutine:\u000a" + this._stack.split("\n").slice(1, -7).join("\n")));
            return;
          }
        }
        maybePromise = maybePromise._target();
        var bitField = maybePromise._bitField;
        ;
        if (((bitField & 50397184) === 0)) {
          this._yieldedPromise = maybePromise;
          maybePromise._proxy(this, null);
        } else if (((bitField & 33554432) !== 0)) {
          this._promiseFulfilled(maybePromise._value());
        } else if (((bitField & 16777216) !== 0)) {
          this._promiseRejected(maybePromise._reason());
        } else {
          this._promiseCancelled();
        }
      }
    };
    Promise.coroutine = function(generatorFunction, options) {
      if (typeof generatorFunction !== "function") {
        throw new TypeError("generatorFunction must be a function\u000a\u000a    See http://goo.gl/MqrFmX\u000a");
      }
      var yieldHandler = Object(options).yieldHandler;
      var PromiseSpawn$ = PromiseSpawn;
      var stack = new Error().stack;
      return function() {
        var generator = generatorFunction.apply(this, arguments);
        var spawn = new PromiseSpawn$(undefined, undefined, yieldHandler, stack);
        var ret = spawn.promise();
        spawn._generator = generator;
        spawn._promiseFulfilled(undefined);
        return ret;
      };
    };
    Promise.coroutine.addYieldHandler = function(fn) {
      if (typeof fn !== "function") {
        throw new TypeError("expecting a function but got " + util.classString(fn));
      }
      yieldHandlers.push(fn);
    };
    Promise.spawn = function(generatorFunction) {
      debug.deprecated("Promise.spawn()", "Promise.coroutine()");
      if (typeof generatorFunction !== "function") {
        return apiRejection("generatorFunction must be a function\u000a\u000a    See http://goo.gl/MqrFmX\u000a");
      }
      var spawn = new PromiseSpawn(generatorFunction, this);
      var ret = spawn.promise();
      spawn._run(Promise.spawn);
      return ret;
    };
  };
  return module.exports;
});

$__System.registerDynamic("56", ["41"], true, function($__require, exports, module) {
  "use strict";
  ;
  var define,
      global = this,
      GLOBAL = this;
  module.exports = function(Promise) {
    var util = $__require('41');
    var async = Promise._async;
    var tryCatch = util.tryCatch;
    var errorObj = util.errorObj;
    function spreadAdapter(val, nodeback) {
      var promise = this;
      if (!util.isArray(val))
        return successAdapter.call(promise, val, nodeback);
      var ret = tryCatch(nodeback).apply(promise._boundValue(), [null].concat(val));
      if (ret === errorObj) {
        async.throwLater(ret.e);
      }
    }
    function successAdapter(val, nodeback) {
      var promise = this;
      var receiver = promise._boundValue();
      var ret = val === undefined ? tryCatch(nodeback).call(receiver, null) : tryCatch(nodeback).call(receiver, null, val);
      if (ret === errorObj) {
        async.throwLater(ret.e);
      }
    }
    function errorAdapter(reason, nodeback) {
      var promise = this;
      if (!reason) {
        var newReason = new Error(reason + "");
        newReason.cause = reason;
        reason = newReason;
      }
      var ret = tryCatch(nodeback).call(promise._boundValue(), reason);
      if (ret === errorObj) {
        async.throwLater(ret.e);
      }
    }
    Promise.prototype.asCallback = Promise.prototype.nodeify = function(nodeback, options) {
      if (typeof nodeback == "function") {
        var adapter = successAdapter;
        if (options !== undefined && Object(options).spread) {
          adapter = spreadAdapter;
        }
        this._then(adapter, errorAdapter, undefined, this, nodeback);
      }
      return this;
    };
  };
  return module.exports;
});

$__System.registerDynamic("57", ["41"], true, function($__require, exports, module) {
  "use strict";
  ;
  var define,
      global = this,
      GLOBAL = this;
  var cr = Object.create;
  if (cr) {
    var callerCache = cr(null);
    var getterCache = cr(null);
    callerCache[" size"] = getterCache[" size"] = 0;
  }
  module.exports = function(Promise) {
    var util = $__require('41');
    var canEvaluate = util.canEvaluate;
    var isIdentifier = util.isIdentifier;
    var getMethodCaller;
    var getGetter;
    if (!false) {
      var makeMethodCaller = function(methodName) {
        return new Function("ensureMethod", "                                    \n\
        return function(obj) {                                               \n\
            'use strict'                                                     \n\
            var len = this.length;                                           \n\
            ensureMethod(obj, 'methodName');                                 \n\
            switch(len) {                                                    \n\
                case 1: return obj.methodName(this[0]);                      \n\
                case 2: return obj.methodName(this[0], this[1]);             \n\
                case 3: return obj.methodName(this[0], this[1], this[2]);    \n\
                case 0: return obj.methodName();                             \n\
                default:                                                     \n\
                    return obj.methodName.apply(obj, this);                  \n\
            }                                                                \n\
        };                                                                   \n\
        ".replace(/methodName/g, methodName))(ensureMethod);
      };
      var makeGetter = function(propertyName) {
        return new Function("obj", "                                             \n\
        'use strict';                                                        \n\
        return obj.propertyName;                                             \n\
        ".replace("propertyName", propertyName));
      };
      var getCompiled = function(name, compiler, cache) {
        var ret = cache[name];
        if (typeof ret !== "function") {
          if (!isIdentifier(name)) {
            return null;
          }
          ret = compiler(name);
          cache[name] = ret;
          cache[" size"]++;
          if (cache[" size"] > 512) {
            var keys = Object.keys(cache);
            for (var i = 0; i < 256; ++i)
              delete cache[keys[i]];
            cache[" size"] = keys.length - 256;
          }
        }
        return ret;
      };
      getMethodCaller = function(name) {
        return getCompiled(name, makeMethodCaller, callerCache);
      };
      getGetter = function(name) {
        return getCompiled(name, makeGetter, getterCache);
      };
    }
    function ensureMethod(obj, methodName) {
      var fn;
      if (obj != null)
        fn = obj[methodName];
      if (typeof fn !== "function") {
        var message = "Object " + util.classString(obj) + " has no method '" + util.toString(methodName) + "'";
        throw new Promise.TypeError(message);
      }
      return fn;
    }
    function caller(obj) {
      var methodName = this.pop();
      var fn = ensureMethod(obj, methodName);
      return fn.apply(obj, this);
    }
    Promise.prototype.call = function(methodName) {
      var $_len = arguments.length;
      var args = new Array($_len - 1);
      for (var $_i = 1; $_i < $_len; ++$_i) {
        args[$_i - 1] = arguments[$_i];
      }
      ;
      if (!false) {
        if (canEvaluate) {
          var maybeCaller = getMethodCaller(methodName);
          if (maybeCaller !== null) {
            return this._then(maybeCaller, undefined, undefined, args, undefined);
          }
        }
      }
      args.push(methodName);
      return this._then(caller, undefined, undefined, args, undefined);
    };
    function namedGetter(obj) {
      return obj[this];
    }
    function indexedGetter(obj) {
      var index = +this;
      if (index < 0)
        index = Math.max(0, index + obj.length);
      return obj[index];
    }
    Promise.prototype.get = function(propertyName) {
      var isIndex = (typeof propertyName === "number");
      var getter;
      if (!isIndex) {
        if (canEvaluate) {
          var maybeGetter = getGetter(propertyName);
          getter = maybeGetter !== null ? maybeGetter : namedGetter;
        } else {
          getter = namedGetter;
        }
      } else {
        getter = indexedGetter;
      }
      return this._then(getter, undefined, undefined, propertyName, undefined);
    };
  };
  return module.exports;
});

$__System.registerDynamic("58", ["41", "4b"], true, function($__require, exports, module) {
  "use strict";
  ;
  var define,
      global = this,
      GLOBAL = this;
  module.exports = function(Promise, PromiseArray, tryConvertToPromise, apiRejection) {
    var util = $__require('41');
    var isObject = util.isObject;
    var es5 = $__require('4b');
    var Es6Map;
    if (typeof Map === "function")
      Es6Map = Map;
    var mapToEntries = (function() {
      var index = 0;
      var size = 0;
      function extractEntry(value, key) {
        this[index] = value;
        this[index + size] = key;
        index++;
      }
      return function mapToEntries(map) {
        size = map.size;
        index = 0;
        var ret = new Array(map.size * 2);
        map.forEach(extractEntry, ret);
        return ret;
      };
    })();
    var entriesToMap = function(entries) {
      var ret = new Es6Map();
      var length = entries.length / 2 | 0;
      for (var i = 0; i < length; ++i) {
        var key = entries[length + i];
        var value = entries[i];
        ret.set(key, value);
      }
      return ret;
    };
    function PropertiesPromiseArray(obj) {
      var isMap = false;
      var entries;
      if (Es6Map !== undefined && obj instanceof Es6Map) {
        entries = mapToEntries(obj);
        isMap = true;
      } else {
        var keys = es5.keys(obj);
        var len = keys.length;
        entries = new Array(len * 2);
        for (var i = 0; i < len; ++i) {
          var key = keys[i];
          entries[i] = obj[key];
          entries[i + len] = key;
        }
      }
      this.constructor$(entries);
      this._isMap = isMap;
      this._init$(undefined, -3);
    }
    util.inherits(PropertiesPromiseArray, PromiseArray);
    PropertiesPromiseArray.prototype._init = function() {};
    PropertiesPromiseArray.prototype._promiseFulfilled = function(value, index) {
      this._values[index] = value;
      var totalResolved = ++this._totalResolved;
      if (totalResolved >= this._length) {
        var val;
        if (this._isMap) {
          val = entriesToMap(this._values);
        } else {
          val = {};
          var keyOffset = this.length();
          for (var i = 0,
              len = this.length(); i < len; ++i) {
            val[this._values[i + keyOffset]] = this._values[i];
          }
        }
        this._resolve(val);
        return true;
      }
      return false;
    };
    PropertiesPromiseArray.prototype.shouldCopyValues = function() {
      return false;
    };
    PropertiesPromiseArray.prototype.getActualLength = function(len) {
      return len >> 1;
    };
    function props(promises) {
      var ret;
      var castValue = tryConvertToPromise(promises);
      if (!isObject(castValue)) {
        return apiRejection("cannot await properties of a non-object\u000a\u000a    See http://goo.gl/MqrFmX\u000a");
      } else if (castValue instanceof Promise) {
        ret = castValue._then(Promise.props, undefined, undefined, undefined, undefined);
      } else {
        ret = new PropertiesPromiseArray(castValue).promise();
      }
      if (castValue instanceof Promise) {
        ret._propagateFrom(castValue, 2);
      }
      return ret;
    }
    Promise.prototype.props = function() {
      return props(this);
    };
    Promise.props = function(promises) {
      return props(promises);
    };
  };
  return module.exports;
});

$__System.registerDynamic("59", ["41"], true, function($__require, exports, module) {
  "use strict";
  ;
  var define,
      global = this,
      GLOBAL = this;
  module.exports = function(Promise, INTERNAL, tryConvertToPromise, apiRejection) {
    var util = $__require('41');
    var raceLater = function(promise) {
      return promise.then(function(array) {
        return race(array, promise);
      });
    };
    function race(promises, parent) {
      var maybePromise = tryConvertToPromise(promises);
      if (maybePromise instanceof Promise) {
        return raceLater(maybePromise);
      } else {
        promises = util.asArray(promises);
        if (promises === null)
          return apiRejection("expecting an array or an iterable object but got " + util.classString(promises));
      }
      var ret = new Promise(INTERNAL);
      if (parent !== undefined) {
        ret._propagateFrom(parent, 3);
      }
      var fulfill = ret._fulfill;
      var reject = ret._reject;
      for (var i = 0,
          len = promises.length; i < len; ++i) {
        var val = promises[i];
        if (val === undefined && !(i in promises)) {
          continue;
        }
        Promise.cast(val)._then(fulfill, reject, undefined, ret, null);
      }
      return ret;
    }
    Promise.race = function(promises) {
      return race(promises, undefined);
    };
    Promise.prototype.race = function() {
      return race(this, undefined);
    };
  };
  return module.exports;
});

$__System.registerDynamic("5a", ["41"], true, function($__require, exports, module) {
  "use strict";
  ;
  var define,
      global = this,
      GLOBAL = this;
  module.exports = function(Promise, PromiseArray, apiRejection, tryConvertToPromise, INTERNAL, debug) {
    var getDomain = Promise._getDomain;
    var util = $__require('41');
    var tryCatch = util.tryCatch;
    function ReductionPromiseArray(promises, fn, initialValue, _each) {
      this.constructor$(promises);
      var domain = getDomain();
      this._fn = domain === null ? fn : domain.bind(fn);
      if (initialValue !== undefined) {
        initialValue = Promise.resolve(initialValue);
        initialValue._attachCancellationCallback(this);
      }
      this._initialValue = initialValue;
      this._currentCancellable = null;
      this._eachValues = _each === INTERNAL ? [] : undefined;
      this._promise._captureStackTrace();
      this._init$(undefined, -5);
    }
    util.inherits(ReductionPromiseArray, PromiseArray);
    ReductionPromiseArray.prototype._gotAccum = function(accum) {
      if (this._eachValues !== undefined && accum !== INTERNAL) {
        this._eachValues.push(accum);
      }
    };
    ReductionPromiseArray.prototype._eachComplete = function(value) {
      this._eachValues.push(value);
      return this._eachValues;
    };
    ReductionPromiseArray.prototype._init = function() {};
    ReductionPromiseArray.prototype._resolveEmptyArray = function() {
      this._resolve(this._eachValues !== undefined ? this._eachValues : this._initialValue);
    };
    ReductionPromiseArray.prototype.shouldCopyValues = function() {
      return false;
    };
    ReductionPromiseArray.prototype._resolve = function(value) {
      this._promise._resolveCallback(value);
      this._values = null;
    };
    ReductionPromiseArray.prototype._resultCancelled = function(sender) {
      if (sender === this._initialValue)
        return this._cancel();
      if (this._isResolved())
        return;
      this._resultCancelled$();
      if (this._currentCancellable instanceof Promise) {
        this._currentCancellable.cancel();
      }
      if (this._initialValue instanceof Promise) {
        this._initialValue.cancel();
      }
    };
    ReductionPromiseArray.prototype._iterate = function(values) {
      this._values = values;
      var value;
      var i;
      var length = values.length;
      if (this._initialValue !== undefined) {
        value = this._initialValue;
        i = 0;
      } else {
        value = Promise.resolve(values[0]);
        i = 1;
      }
      this._currentCancellable = value;
      if (!value.isRejected()) {
        for (; i < length; ++i) {
          var ctx = {
            accum: null,
            value: values[i],
            index: i,
            length: length,
            array: this
          };
          value = value._then(gotAccum, undefined, undefined, ctx, undefined);
        }
      }
      if (this._eachValues !== undefined) {
        value = value._then(this._eachComplete, undefined, undefined, this, undefined);
      }
      value._then(completed, completed, undefined, value, this);
    };
    Promise.prototype.reduce = function(fn, initialValue) {
      return reduce(this, fn, initialValue, null);
    };
    Promise.reduce = function(promises, fn, initialValue, _each) {
      return reduce(promises, fn, initialValue, _each);
    };
    function completed(valueOrReason, array) {
      if (this.isFulfilled()) {
        array._resolve(valueOrReason);
      } else {
        array._reject(valueOrReason);
      }
    }
    function reduce(promises, fn, initialValue, _each) {
      if (typeof fn !== "function") {
        return apiRejection("expecting a function but got " + util.classString(fn));
      }
      var array = new ReductionPromiseArray(promises, fn, initialValue, _each);
      return array.promise();
    }
    function gotAccum(accum) {
      this.accum = accum;
      this.array._gotAccum(accum);
      var value = tryConvertToPromise(this.value, this.array._promise);
      if (value instanceof Promise) {
        this.array._currentCancellable = value;
        return value._then(gotValue, undefined, undefined, this, undefined);
      } else {
        return gotValue.call(this, value);
      }
    }
    function gotValue(value) {
      var array = this.array;
      var promise = array._promise;
      var fn = tryCatch(array._fn);
      promise._pushContext();
      var ret;
      if (array._eachValues !== undefined) {
        ret = fn.call(promise._boundValue(), value, this.index, this.length);
      } else {
        ret = fn.call(promise._boundValue(), this.accum, value, this.index, this.length);
      }
      if (ret instanceof Promise) {
        array._currentCancellable = ret;
      }
      var promiseCreated = promise._popContext();
      debug.checkForgottenReturns(ret, promiseCreated, array._eachValues !== undefined ? "Promise.each" : "Promise.reduce", promise);
      return ret;
    }
  };
  return module.exports;
});

$__System.registerDynamic("5b", ["41"], true, function($__require, exports, module) {
  "use strict";
  ;
  var define,
      global = this,
      GLOBAL = this;
  module.exports = function(Promise, PromiseArray, debug) {
    var PromiseInspection = Promise.PromiseInspection;
    var util = $__require('41');
    function SettledPromiseArray(values) {
      this.constructor$(values);
    }
    util.inherits(SettledPromiseArray, PromiseArray);
    SettledPromiseArray.prototype._promiseResolved = function(index, inspection) {
      this._values[index] = inspection;
      var totalResolved = ++this._totalResolved;
      if (totalResolved >= this._length) {
        this._resolve(this._values);
        return true;
      }
      return false;
    };
    SettledPromiseArray.prototype._promiseFulfilled = function(value, index) {
      var ret = new PromiseInspection();
      ret._bitField = 33554432;
      ret._settledValueField = value;
      return this._promiseResolved(index, ret);
    };
    SettledPromiseArray.prototype._promiseRejected = function(reason, index) {
      var ret = new PromiseInspection();
      ret._bitField = 16777216;
      ret._settledValueField = reason;
      return this._promiseResolved(index, ret);
    };
    Promise.settle = function(promises) {
      debug.deprecated(".settle()", ".reflect()");
      return new SettledPromiseArray(promises).promise();
    };
    Promise.prototype.settle = function() {
      return Promise.settle(this);
    };
  };
  return module.exports;
});

$__System.registerDynamic("5c", ["41", "48"], true, function($__require, exports, module) {
  "use strict";
  ;
  var define,
      global = this,
      GLOBAL = this;
  module.exports = function(Promise, PromiseArray, apiRejection) {
    var util = $__require('41');
    var RangeError = $__require('48').RangeError;
    var AggregateError = $__require('48').AggregateError;
    var isArray = util.isArray;
    var CANCELLATION = {};
    function SomePromiseArray(values) {
      this.constructor$(values);
      this._howMany = 0;
      this._unwrap = false;
      this._initialized = false;
    }
    util.inherits(SomePromiseArray, PromiseArray);
    SomePromiseArray.prototype._init = function() {
      if (!this._initialized) {
        return;
      }
      if (this._howMany === 0) {
        this._resolve([]);
        return;
      }
      this._init$(undefined, -5);
      var isArrayResolved = isArray(this._values);
      if (!this._isResolved() && isArrayResolved && this._howMany > this._canPossiblyFulfill()) {
        this._reject(this._getRangeError(this.length()));
      }
    };
    SomePromiseArray.prototype.init = function() {
      this._initialized = true;
      this._init();
    };
    SomePromiseArray.prototype.setUnwrap = function() {
      this._unwrap = true;
    };
    SomePromiseArray.prototype.howMany = function() {
      return this._howMany;
    };
    SomePromiseArray.prototype.setHowMany = function(count) {
      this._howMany = count;
    };
    SomePromiseArray.prototype._promiseFulfilled = function(value) {
      this._addFulfilled(value);
      if (this._fulfilled() === this.howMany()) {
        this._values.length = this.howMany();
        if (this.howMany() === 1 && this._unwrap) {
          this._resolve(this._values[0]);
        } else {
          this._resolve(this._values);
        }
        return true;
      }
      return false;
    };
    SomePromiseArray.prototype._promiseRejected = function(reason) {
      this._addRejected(reason);
      return this._checkOutcome();
    };
    SomePromiseArray.prototype._promiseCancelled = function() {
      if (this._values instanceof Promise || this._values == null) {
        return this._cancel();
      }
      this._addRejected(CANCELLATION);
      return this._checkOutcome();
    };
    SomePromiseArray.prototype._checkOutcome = function() {
      if (this.howMany() > this._canPossiblyFulfill()) {
        var e = new AggregateError();
        for (var i = this.length(); i < this._values.length; ++i) {
          if (this._values[i] !== CANCELLATION) {
            e.push(this._values[i]);
          }
        }
        if (e.length > 0) {
          this._reject(e);
        } else {
          this._cancel();
        }
        return true;
      }
      return false;
    };
    SomePromiseArray.prototype._fulfilled = function() {
      return this._totalResolved;
    };
    SomePromiseArray.prototype._rejected = function() {
      return this._values.length - this.length();
    };
    SomePromiseArray.prototype._addRejected = function(reason) {
      this._values.push(reason);
    };
    SomePromiseArray.prototype._addFulfilled = function(value) {
      this._values[this._totalResolved++] = value;
    };
    SomePromiseArray.prototype._canPossiblyFulfill = function() {
      return this.length() - this._rejected();
    };
    SomePromiseArray.prototype._getRangeError = function(count) {
      var message = "Input array must contain at least " + this._howMany + " items but contains only " + count + " items";
      return new RangeError(message);
    };
    SomePromiseArray.prototype._resolveEmptyArray = function() {
      this._reject(this._getRangeError(0));
    };
    function some(promises, howMany) {
      if ((howMany | 0) !== howMany || howMany < 0) {
        return apiRejection("expecting a positive integer\u000a\u000a    See http://goo.gl/MqrFmX\u000a");
      }
      var ret = new SomePromiseArray(promises);
      var promise = ret.promise();
      ret.setHowMany(howMany);
      ret.init();
      return promise;
    }
    Promise.some = function(promises, howMany) {
      return some(promises, howMany);
    };
    Promise.prototype.some = function(howMany) {
      return some(this, howMany);
    };
    Promise._SomePromiseArray = SomePromiseArray;
  };
  return module.exports;
});

$__System.registerDynamic("5d", ["41", "48", "4b"], true, function($__require, exports, module) {
  "use strict";
  ;
  var define,
      global = this,
      GLOBAL = this;
  var util = $__require('41');
  var maybeWrapAsError = util.maybeWrapAsError;
  var errors = $__require('48');
  var OperationalError = errors.OperationalError;
  var es5 = $__require('4b');
  function isUntypedError(obj) {
    return obj instanceof Error && es5.getPrototypeOf(obj) === Error.prototype;
  }
  var rErrorKey = /^(?:name|message|stack|cause)$/;
  function wrapAsOperationalError(obj) {
    var ret;
    if (isUntypedError(obj)) {
      ret = new OperationalError(obj);
      ret.name = obj.name;
      ret.message = obj.message;
      ret.stack = obj.stack;
      var keys = es5.keys(obj);
      for (var i = 0; i < keys.length; ++i) {
        var key = keys[i];
        if (!rErrorKey.test(key)) {
          ret[key] = obj[key];
        }
      }
      return ret;
    }
    util.markAsOriginatingFromRejection(obj);
    return obj;
  }
  function nodebackForPromise(promise, multiArgs) {
    return function(err, value) {
      if (promise === null)
        return;
      if (err) {
        var wrapped = wrapAsOperationalError(maybeWrapAsError(err));
        promise._attachExtraTrace(wrapped);
        promise._reject(wrapped);
      } else if (!multiArgs) {
        promise._fulfill(value);
      } else {
        var $_len = arguments.length;
        var args = new Array($_len - 1);
        for (var $_i = 1; $_i < $_len; ++$_i) {
          args[$_i - 1] = arguments[$_i];
        }
        ;
        promise._fulfill(args);
      }
      promise = null;
    };
  }
  module.exports = nodebackForPromise;
  return module.exports;
});

$__System.registerDynamic("4b", [], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  var isES5 = (function() {
    "use strict";
    return this === undefined;
  })();
  if (isES5) {
    module.exports = {
      freeze: Object.freeze,
      defineProperty: Object.defineProperty,
      getDescriptor: Object.getOwnPropertyDescriptor,
      keys: Object.keys,
      names: Object.getOwnPropertyNames,
      getPrototypeOf: Object.getPrototypeOf,
      isArray: Array.isArray,
      isES5: isES5,
      propertyIsWritable: function(obj, prop) {
        var descriptor = Object.getOwnPropertyDescriptor(obj, prop);
        return !!(!descriptor || descriptor.writable || descriptor.set);
      }
    };
  } else {
    var has = {}.hasOwnProperty;
    var str = {}.toString;
    var proto = {}.constructor.prototype;
    var ObjectKeys = function(o) {
      var ret = [];
      for (var key in o) {
        if (has.call(o, key)) {
          ret.push(key);
        }
      }
      return ret;
    };
    var ObjectGetDescriptor = function(o, key) {
      return {value: o[key]};
    };
    var ObjectDefineProperty = function(o, key, desc) {
      o[key] = desc.value;
      return o;
    };
    var ObjectFreeze = function(obj) {
      return obj;
    };
    var ObjectGetPrototypeOf = function(obj) {
      try {
        return Object(obj).constructor.prototype;
      } catch (e) {
        return proto;
      }
    };
    var ArrayIsArray = function(obj) {
      try {
        return str.call(obj) === "[object Array]";
      } catch (e) {
        return false;
      }
    };
    module.exports = {
      isArray: ArrayIsArray,
      keys: ObjectKeys,
      names: ObjectKeys,
      defineProperty: ObjectDefineProperty,
      getDescriptor: ObjectGetDescriptor,
      freeze: ObjectFreeze,
      getPrototypeOf: ObjectGetPrototypeOf,
      isES5: isES5,
      propertyIsWritable: function() {
        return true;
      }
    };
  }
  return module.exports;
});

$__System.registerDynamic("41", ["4b"], true, function($__require, exports, module) {
  "use strict";
  ;
  var define,
      global = this,
      GLOBAL = this;
  var es5 = $__require('4b');
  var canEvaluate = typeof navigator == "undefined";
  var errorObj = {e: {}};
  var tryCatchTarget;
  var globalObject = typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : this !== undefined ? this : null;
  function tryCatcher() {
    try {
      var target = tryCatchTarget;
      tryCatchTarget = null;
      return target.apply(this, arguments);
    } catch (e) {
      errorObj.e = e;
      return errorObj;
    }
  }
  function tryCatch(fn) {
    tryCatchTarget = fn;
    return tryCatcher;
  }
  var inherits = function(Child, Parent) {
    var hasProp = {}.hasOwnProperty;
    function T() {
      this.constructor = Child;
      this.constructor$ = Parent;
      for (var propertyName in Parent.prototype) {
        if (hasProp.call(Parent.prototype, propertyName) && propertyName.charAt(propertyName.length - 1) !== "$") {
          this[propertyName + "$"] = Parent.prototype[propertyName];
        }
      }
    }
    T.prototype = Parent.prototype;
    Child.prototype = new T();
    return Child.prototype;
  };
  function isPrimitive(val) {
    return val == null || val === true || val === false || typeof val === "string" || typeof val === "number";
  }
  function isObject(value) {
    return typeof value === "function" || typeof value === "object" && value !== null;
  }
  function maybeWrapAsError(maybeError) {
    if (!isPrimitive(maybeError))
      return maybeError;
    return new Error(safeToString(maybeError));
  }
  function withAppended(target, appendee) {
    var len = target.length;
    var ret = new Array(len + 1);
    var i;
    for (i = 0; i < len; ++i) {
      ret[i] = target[i];
    }
    ret[i] = appendee;
    return ret;
  }
  function getDataPropertyOrDefault(obj, key, defaultValue) {
    if (es5.isES5) {
      var desc = Object.getOwnPropertyDescriptor(obj, key);
      if (desc != null) {
        return desc.get == null && desc.set == null ? desc.value : defaultValue;
      }
    } else {
      return {}.hasOwnProperty.call(obj, key) ? obj[key] : undefined;
    }
  }
  function notEnumerableProp(obj, name, value) {
    if (isPrimitive(obj))
      return obj;
    var descriptor = {
      value: value,
      configurable: true,
      enumerable: false,
      writable: true
    };
    es5.defineProperty(obj, name, descriptor);
    return obj;
  }
  function thrower(r) {
    throw r;
  }
  var inheritedDataKeys = (function() {
    var excludedPrototypes = [Array.prototype, Object.prototype, Function.prototype];
    var isExcludedProto = function(val) {
      for (var i = 0; i < excludedPrototypes.length; ++i) {
        if (excludedPrototypes[i] === val) {
          return true;
        }
      }
      return false;
    };
    if (es5.isES5) {
      var getKeys = Object.getOwnPropertyNames;
      return function(obj) {
        var ret = [];
        var visitedKeys = Object.create(null);
        while (obj != null && !isExcludedProto(obj)) {
          var keys;
          try {
            keys = getKeys(obj);
          } catch (e) {
            return ret;
          }
          for (var i = 0; i < keys.length; ++i) {
            var key = keys[i];
            if (visitedKeys[key])
              continue;
            visitedKeys[key] = true;
            var desc = Object.getOwnPropertyDescriptor(obj, key);
            if (desc != null && desc.get == null && desc.set == null) {
              ret.push(key);
            }
          }
          obj = es5.getPrototypeOf(obj);
        }
        return ret;
      };
    } else {
      var hasProp = {}.hasOwnProperty;
      return function(obj) {
        if (isExcludedProto(obj))
          return [];
        var ret = [];
        enumeration: for (var key in obj) {
          if (hasProp.call(obj, key)) {
            ret.push(key);
          } else {
            for (var i = 0; i < excludedPrototypes.length; ++i) {
              if (hasProp.call(excludedPrototypes[i], key)) {
                continue enumeration;
              }
            }
            ret.push(key);
          }
        }
        return ret;
      };
    }
  })();
  var thisAssignmentPattern = /this\s*\.\s*\S+\s*=/;
  function isClass(fn) {
    try {
      if (typeof fn === "function") {
        var keys = es5.names(fn.prototype);
        var hasMethods = es5.isES5 && keys.length > 1;
        var hasMethodsOtherThanConstructor = keys.length > 0 && !(keys.length === 1 && keys[0] === "constructor");
        var hasThisAssignmentAndStaticMethods = thisAssignmentPattern.test(fn + "") && es5.names(fn).length > 0;
        if (hasMethods || hasMethodsOtherThanConstructor || hasThisAssignmentAndStaticMethods) {
          return true;
        }
      }
      return false;
    } catch (e) {
      return false;
    }
  }
  function toFastProperties(obj) {
    function FakeConstructor() {}
    FakeConstructor.prototype = obj;
    var l = 8;
    while (l--)
      new FakeConstructor();
    return obj;
    eval(obj);
  }
  var rident = /^[a-z$_][a-z$_0-9]*$/i;
  function isIdentifier(str) {
    return rident.test(str);
  }
  function filledRange(count, prefix, suffix) {
    var ret = new Array(count);
    for (var i = 0; i < count; ++i) {
      ret[i] = prefix + i + suffix;
    }
    return ret;
  }
  function safeToString(obj) {
    try {
      return obj + "";
    } catch (e) {
      return "[no string representation]";
    }
  }
  function isError(obj) {
    return obj !== null && typeof obj === "object" && typeof obj.message === "string" && typeof obj.name === "string";
  }
  function markAsOriginatingFromRejection(e) {
    try {
      notEnumerableProp(e, "isOperational", true);
    } catch (ignore) {}
  }
  function originatesFromRejection(e) {
    if (e == null)
      return false;
    return ((e instanceof Error["__BluebirdErrorTypes__"].OperationalError) || e["isOperational"] === true);
  }
  function canAttachTrace(obj) {
    return isError(obj) && es5.propertyIsWritable(obj, "stack");
  }
  var ensureErrorObject = (function() {
    if (!("stack" in new Error())) {
      return function(value) {
        if (canAttachTrace(value))
          return value;
        try {
          throw new Error(safeToString(value));
        } catch (err) {
          return err;
        }
      };
    } else {
      return function(value) {
        if (canAttachTrace(value))
          return value;
        return new Error(safeToString(value));
      };
    }
  })();
  function classString(obj) {
    return {}.toString.call(obj);
  }
  function copyDescriptors(from, to, filter) {
    var keys = es5.names(from);
    for (var i = 0; i < keys.length; ++i) {
      var key = keys[i];
      if (filter(key)) {
        try {
          es5.defineProperty(to, key, es5.getDescriptor(from, key));
        } catch (ignore) {}
      }
    }
  }
  var asArray = function(v) {
    if (es5.isArray(v)) {
      return v;
    }
    return null;
  };
  if (typeof Symbol !== "undefined" && Symbol.iterator) {
    var ArrayFrom = typeof Array.from === "function" ? function(v) {
      return Array.from(v);
    } : function(v) {
      var ret = [];
      var it = v[Symbol.iterator]();
      var itResult;
      while (!((itResult = it.next()).done)) {
        ret.push(itResult.value);
      }
      return ret;
    };
    asArray = function(v) {
      if (es5.isArray(v)) {
        return v;
      } else if (v != null && typeof v[Symbol.iterator] === "function") {
        return ArrayFrom(v);
      }
      return null;
    };
  }
  var isNode = typeof process !== "undefined" && classString(process).toLowerCase() === "[object process]";
  function env(key, def) {
    return isNode ? process.env[key] : def;
  }
  var ret = {
    isClass: isClass,
    isIdentifier: isIdentifier,
    inheritedDataKeys: inheritedDataKeys,
    getDataPropertyOrDefault: getDataPropertyOrDefault,
    thrower: thrower,
    isArray: es5.isArray,
    asArray: asArray,
    notEnumerableProp: notEnumerableProp,
    isPrimitive: isPrimitive,
    isObject: isObject,
    isError: isError,
    canEvaluate: canEvaluate,
    errorObj: errorObj,
    tryCatch: tryCatch,
    inherits: inherits,
    withAppended: withAppended,
    maybeWrapAsError: maybeWrapAsError,
    toFastProperties: toFastProperties,
    filledRange: filledRange,
    toString: safeToString,
    canAttachTrace: canAttachTrace,
    ensureErrorObject: ensureErrorObject,
    originatesFromRejection: originatesFromRejection,
    markAsOriginatingFromRejection: markAsOriginatingFromRejection,
    classString: classString,
    copyDescriptors: copyDescriptors,
    hasDevTools: typeof chrome !== "undefined" && chrome && typeof chrome.loadTimes === "function",
    isNode: isNode,
    env: env,
    global: globalObject
  };
  ret.isRecentNode = ret.isNode && (function() {
    var version = process.versions.node.split(".").map(Number);
    return (version[0] === 0 && version[1] > 10) || (version[0] > 0);
  })();
  if (ret.isNode)
    ret.toFastProperties(process);
  try {
    throw new Error();
  } catch (e) {
    ret.lastLineError = e;
  }
  module.exports = ret;
  return module.exports;
});

$__System.registerDynamic("48", ["4b", "41"], true, function($__require, exports, module) {
  "use strict";
  ;
  var define,
      global = this,
      GLOBAL = this;
  var es5 = $__require('4b');
  var Objectfreeze = es5.freeze;
  var util = $__require('41');
  var inherits = util.inherits;
  var notEnumerableProp = util.notEnumerableProp;
  function subError(nameProperty, defaultMessage) {
    function SubError(message) {
      if (!(this instanceof SubError))
        return new SubError(message);
      notEnumerableProp(this, "message", typeof message === "string" ? message : defaultMessage);
      notEnumerableProp(this, "name", nameProperty);
      if (Error.captureStackTrace) {
        Error.captureStackTrace(this, this.constructor);
      } else {
        Error.call(this);
      }
    }
    inherits(SubError, Error);
    return SubError;
  }
  var _TypeError,
      _RangeError;
  var Warning = subError("Warning", "warning");
  var CancellationError = subError("CancellationError", "cancellation error");
  var TimeoutError = subError("TimeoutError", "timeout error");
  var AggregateError = subError("AggregateError", "aggregate error");
  try {
    _TypeError = TypeError;
    _RangeError = RangeError;
  } catch (e) {
    _TypeError = subError("TypeError", "type error");
    _RangeError = subError("RangeError", "range error");
  }
  var methods = ("join pop push shift unshift slice filter forEach some " + "every map indexOf lastIndexOf reduce reduceRight sort reverse").split(" ");
  for (var i = 0; i < methods.length; ++i) {
    if (typeof Array.prototype[methods[i]] === "function") {
      AggregateError.prototype[methods[i]] = Array.prototype[methods[i]];
    }
  }
  es5.defineProperty(AggregateError.prototype, "length", {
    value: 0,
    configurable: false,
    writable: true,
    enumerable: true
  });
  AggregateError.prototype["isOperational"] = true;
  var level = 0;
  AggregateError.prototype.toString = function() {
    var indent = Array(level * 4 + 1).join(" ");
    var ret = "\n" + indent + "AggregateError of:" + "\n";
    level++;
    indent = Array(level * 4 + 1).join(" ");
    for (var i = 0; i < this.length; ++i) {
      var str = this[i] === this ? "[Circular AggregateError]" : this[i] + "";
      var lines = str.split("\n");
      for (var j = 0; j < lines.length; ++j) {
        lines[j] = indent + lines[j];
      }
      str = lines.join("\n");
      ret += str + "\n";
    }
    level--;
    return ret;
  };
  function OperationalError(message) {
    if (!(this instanceof OperationalError))
      return new OperationalError(message);
    notEnumerableProp(this, "name", "OperationalError");
    notEnumerableProp(this, "message", message);
    this.cause = message;
    this["isOperational"] = true;
    if (message instanceof Error) {
      notEnumerableProp(this, "message", message.message);
      notEnumerableProp(this, "stack", message.stack);
    } else if (Error.captureStackTrace) {
      Error.captureStackTrace(this, this.constructor);
    }
  }
  inherits(OperationalError, Error);
  var errorTypes = Error["__BluebirdErrorTypes__"];
  if (!errorTypes) {
    errorTypes = Objectfreeze({
      CancellationError: CancellationError,
      TimeoutError: TimeoutError,
      OperationalError: OperationalError,
      RejectionError: OperationalError,
      AggregateError: AggregateError
    });
    es5.defineProperty(Error, "__BluebirdErrorTypes__", {
      value: errorTypes,
      writable: false,
      enumerable: false,
      configurable: false
    });
  }
  module.exports = {
    Error: Error,
    TypeError: _TypeError,
    RangeError: _RangeError,
    CancellationError: errorTypes.CancellationError,
    OperationalError: errorTypes.OperationalError,
    TimeoutError: errorTypes.TimeoutError,
    AggregateError: errorTypes.AggregateError,
    Warning: Warning
  };
  return module.exports;
});

$__System.registerDynamic("5e", ["41", "5d", "48"], true, function($__require, exports, module) {
  "use strict";
  ;
  var define,
      global = this,
      GLOBAL = this;
  module.exports = function(Promise, INTERNAL) {
    var THIS = {};
    var util = $__require('41');
    var nodebackForPromise = $__require('5d');
    var withAppended = util.withAppended;
    var maybeWrapAsError = util.maybeWrapAsError;
    var canEvaluate = util.canEvaluate;
    var TypeError = $__require('48').TypeError;
    var defaultSuffix = "Async";
    var defaultPromisified = {__isPromisified__: true};
    var noCopyProps = ["arity", "length", "name", "arguments", "caller", "callee", "prototype", "__isPromisified__"];
    var noCopyPropsPattern = new RegExp("^(?:" + noCopyProps.join("|") + ")$");
    var defaultFilter = function(name) {
      return util.isIdentifier(name) && name.charAt(0) !== "_" && name !== "constructor";
    };
    function propsFilter(key) {
      return !noCopyPropsPattern.test(key);
    }
    function isPromisified(fn) {
      try {
        return fn.__isPromisified__ === true;
      } catch (e) {
        return false;
      }
    }
    function hasPromisified(obj, key, suffix) {
      var val = util.getDataPropertyOrDefault(obj, key + suffix, defaultPromisified);
      return val ? isPromisified(val) : false;
    }
    function checkValid(ret, suffix, suffixRegexp) {
      for (var i = 0; i < ret.length; i += 2) {
        var key = ret[i];
        if (suffixRegexp.test(key)) {
          var keyWithoutAsyncSuffix = key.replace(suffixRegexp, "");
          for (var j = 0; j < ret.length; j += 2) {
            if (ret[j] === keyWithoutAsyncSuffix) {
              throw new TypeError("Cannot promisify an API that has normal methods with '%s'-suffix\u000a\u000a    See http://goo.gl/MqrFmX\u000a".replace("%s", suffix));
            }
          }
        }
      }
    }
    function promisifiableMethods(obj, suffix, suffixRegexp, filter) {
      var keys = util.inheritedDataKeys(obj);
      var ret = [];
      for (var i = 0; i < keys.length; ++i) {
        var key = keys[i];
        var value = obj[key];
        var passesDefaultFilter = filter === defaultFilter ? true : defaultFilter(key, value, obj);
        if (typeof value === "function" && !isPromisified(value) && !hasPromisified(obj, key, suffix) && filter(key, value, obj, passesDefaultFilter)) {
          ret.push(key, value);
        }
      }
      checkValid(ret, suffix, suffixRegexp);
      return ret;
    }
    var escapeIdentRegex = function(str) {
      return str.replace(/([$])/, "\\$");
    };
    var makeNodePromisifiedEval;
    if (!false) {
      var switchCaseArgumentOrder = function(likelyArgumentCount) {
        var ret = [likelyArgumentCount];
        var min = Math.max(0, likelyArgumentCount - 1 - 3);
        for (var i = likelyArgumentCount - 1; i >= min; --i) {
          ret.push(i);
        }
        for (var i = likelyArgumentCount + 1; i <= 3; ++i) {
          ret.push(i);
        }
        return ret;
      };
      var argumentSequence = function(argumentCount) {
        return util.filledRange(argumentCount, "_arg", "");
      };
      var parameterDeclaration = function(parameterCount) {
        return util.filledRange(Math.max(parameterCount, 3), "_arg", "");
      };
      var parameterCount = function(fn) {
        if (typeof fn.length === "number") {
          return Math.max(Math.min(fn.length, 1023 + 1), 0);
        }
        return 0;
      };
      makeNodePromisifiedEval = function(callback, receiver, originalName, fn, _, multiArgs) {
        var newParameterCount = Math.max(0, parameterCount(fn) - 1);
        var argumentOrder = switchCaseArgumentOrder(newParameterCount);
        var shouldProxyThis = typeof callback === "string" || receiver === THIS;
        function generateCallForArgumentCount(count) {
          var args = argumentSequence(count).join(", ");
          var comma = count > 0 ? ", " : "";
          var ret;
          if (shouldProxyThis) {
            ret = "ret = callback.call(this, {{args}}, nodeback); break;\n";
          } else {
            ret = receiver === undefined ? "ret = callback({{args}}, nodeback); break;\n" : "ret = callback.call(receiver, {{args}}, nodeback); break;\n";
          }
          return ret.replace("{{args}}", args).replace(", ", comma);
        }
        function generateArgumentSwitchCase() {
          var ret = "";
          for (var i = 0; i < argumentOrder.length; ++i) {
            ret += "case " + argumentOrder[i] + ":" + generateCallForArgumentCount(argumentOrder[i]);
          }
          ret += "                                                             \n\
        default:                                                             \n\
            var args = new Array(len + 1);                                   \n\
            var i = 0;                                                       \n\
            for (var i = 0; i < len; ++i) {                                  \n\
               args[i] = arguments[i];                                       \n\
            }                                                                \n\
            args[i] = nodeback;                                              \n\
            [CodeForCall]                                                    \n\
            break;                                                           \n\
        ".replace("[CodeForCall]", (shouldProxyThis ? "ret = callback.apply(this, args);\n" : "ret = callback.apply(receiver, args);\n"));
          return ret;
        }
        var getFunctionCode = typeof callback === "string" ? ("this != null ? this['" + callback + "'] : fn") : "fn";
        var body = "'use strict';                                                \n\
        var ret = function (Parameters) {                                    \n\
            'use strict';                                                    \n\
            var len = arguments.length;                                      \n\
            var promise = new Promise(INTERNAL);                             \n\
            promise._captureStackTrace();                                    \n\
            var nodeback = nodebackForPromise(promise, " + multiArgs + ");   \n\
            var ret;                                                         \n\
            var callback = tryCatch([GetFunctionCode]);                      \n\
            switch(len) {                                                    \n\
                [CodeForSwitchCase]                                          \n\
            }                                                                \n\
            if (ret === errorObj) {                                          \n\
                promise._rejectCallback(maybeWrapAsError(ret.e), true, true);\n\
            }                                                                \n\
            if (!promise._isFateSealed()) promise._setAsyncGuaranteed();     \n\
            return promise;                                                  \n\
        };                                                                   \n\
        notEnumerableProp(ret, '__isPromisified__', true);                   \n\
        return ret;                                                          \n\
    ".replace("[CodeForSwitchCase]", generateArgumentSwitchCase()).replace("[GetFunctionCode]", getFunctionCode);
        body = body.replace("Parameters", parameterDeclaration(newParameterCount));
        return new Function("Promise", "fn", "receiver", "withAppended", "maybeWrapAsError", "nodebackForPromise", "tryCatch", "errorObj", "notEnumerableProp", "INTERNAL", body)(Promise, fn, receiver, withAppended, maybeWrapAsError, nodebackForPromise, util.tryCatch, util.errorObj, util.notEnumerableProp, INTERNAL);
      };
    }
    function makeNodePromisifiedClosure(callback, receiver, _, fn, __, multiArgs) {
      var defaultThis = (function() {
        return this;
      })();
      var method = callback;
      if (typeof method === "string") {
        callback = fn;
      }
      function promisified() {
        var _receiver = receiver;
        if (receiver === THIS)
          _receiver = this;
        var promise = new Promise(INTERNAL);
        promise._captureStackTrace();
        var cb = typeof method === "string" && this !== defaultThis ? this[method] : callback;
        var fn = nodebackForPromise(promise, multiArgs);
        try {
          cb.apply(_receiver, withAppended(arguments, fn));
        } catch (e) {
          promise._rejectCallback(maybeWrapAsError(e), true, true);
        }
        if (!promise._isFateSealed())
          promise._setAsyncGuaranteed();
        return promise;
      }
      util.notEnumerableProp(promisified, "__isPromisified__", true);
      return promisified;
    }
    var makeNodePromisified = canEvaluate ? makeNodePromisifiedEval : makeNodePromisifiedClosure;
    function promisifyAll(obj, suffix, filter, promisifier, multiArgs) {
      var suffixRegexp = new RegExp(escapeIdentRegex(suffix) + "$");
      var methods = promisifiableMethods(obj, suffix, suffixRegexp, filter);
      for (var i = 0,
          len = methods.length; i < len; i += 2) {
        var key = methods[i];
        var fn = methods[i + 1];
        var promisifiedKey = key + suffix;
        if (promisifier === makeNodePromisified) {
          obj[promisifiedKey] = makeNodePromisified(key, THIS, key, fn, suffix, multiArgs);
        } else {
          var promisified = promisifier(fn, function() {
            return makeNodePromisified(key, THIS, key, fn, suffix, multiArgs);
          });
          util.notEnumerableProp(promisified, "__isPromisified__", true);
          obj[promisifiedKey] = promisified;
        }
      }
      util.toFastProperties(obj);
      return obj;
    }
    function promisify(callback, receiver, multiArgs) {
      return makeNodePromisified(callback, receiver, undefined, callback, null, multiArgs);
    }
    Promise.promisify = function(fn, options) {
      if (typeof fn !== "function") {
        throw new TypeError("expecting a function but got " + util.classString(fn));
      }
      if (isPromisified(fn)) {
        return fn;
      }
      options = Object(options);
      var receiver = options.context === undefined ? THIS : options.context;
      var multiArgs = !!options.multiArgs;
      var ret = promisify(fn, receiver, multiArgs);
      util.copyDescriptors(fn, ret, propsFilter);
      return ret;
    };
    Promise.promisifyAll = function(target, options) {
      if (typeof target !== "function" && typeof target !== "object") {
        throw new TypeError("the target of promisifyAll must be an object or a function\u000a\u000a    See http://goo.gl/MqrFmX\u000a");
      }
      options = Object(options);
      var multiArgs = !!options.multiArgs;
      var suffix = options.suffix;
      if (typeof suffix !== "string")
        suffix = defaultSuffix;
      var filter = options.filter;
      if (typeof filter !== "function")
        filter = defaultFilter;
      var promisifier = options.promisifier;
      if (typeof promisifier !== "function")
        promisifier = makeNodePromisified;
      if (!util.isIdentifier(suffix)) {
        throw new RangeError("suffix must be a valid identifier\u000a\u000a    See http://goo.gl/MqrFmX\u000a");
      }
      var keys = util.inheritedDataKeys(target);
      for (var i = 0; i < keys.length; ++i) {
        var value = target[keys[i]];
        if (keys[i] !== "constructor" && util.isClass(value)) {
          promisifyAll(value.prototype, suffix, filter, promisifier, multiArgs);
          promisifyAll(value, suffix, filter, promisifier, multiArgs);
        }
      }
      return promisifyAll(target, suffix, filter, promisifier, multiArgs);
    };
  };
  return module.exports;
});

$__System.registerDynamic("5f", [], true, function($__require, exports, module) {
  "use strict";
  ;
  var define,
      global = this,
      GLOBAL = this;
  module.exports = function(Promise) {
    var SomePromiseArray = Promise._SomePromiseArray;
    function any(promises) {
      var ret = new SomePromiseArray(promises);
      var promise = ret.promise();
      ret.setHowMany(1);
      ret.setUnwrap();
      ret.init();
      return promise;
    }
    Promise.any = function(promises) {
      return any(promises);
    };
    Promise.prototype.any = function() {
      return any(this);
    };
  };
  return module.exports;
});

$__System.registerDynamic("60", [], true, function($__require, exports, module) {
  "use strict";
  ;
  var define,
      global = this,
      GLOBAL = this;
  module.exports = function(Promise, INTERNAL) {
    var PromiseReduce = Promise.reduce;
    var PromiseAll = Promise.all;
    function promiseAllThis() {
      return PromiseAll(this);
    }
    function PromiseMapSeries(promises, fn) {
      return PromiseReduce(promises, fn, INTERNAL, INTERNAL);
    }
    Promise.prototype.each = function(fn) {
      return this.mapSeries(fn)._then(promiseAllThis, undefined, undefined, this, undefined);
    };
    Promise.prototype.mapSeries = function(fn) {
      return PromiseReduce(this, fn, INTERNAL, INTERNAL);
    };
    Promise.each = function(promises, fn) {
      return PromiseMapSeries(promises, fn)._then(promiseAllThis, undefined, undefined, promises, undefined);
    };
    Promise.mapSeries = PromiseMapSeries;
  };
  return module.exports;
});

$__System.registerDynamic("61", [], true, function($__require, exports, module) {
  "use strict";
  ;
  var define,
      global = this,
      GLOBAL = this;
  module.exports = function(Promise, INTERNAL) {
    var PromiseMap = Promise.map;
    Promise.prototype.filter = function(fn, options) {
      return PromiseMap(this, fn, options, INTERNAL);
    };
    Promise.filter = function(promises, fn, options) {
      return PromiseMap(promises, fn, options, INTERNAL);
    };
  };
  return module.exports;
});

$__System.registerDynamic("62", ["41", "4b", "43", "48", "44", "45", "46", "47", "49", "4a", "5d", "4c", "4d", "4e", "4f", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5a", "5b", "5c", "5e", "5f", "60", "61"], true, function($__require, exports, module) {
  "use strict";
  ;
  var define,
      global = this,
      GLOBAL = this;
  module.exports = function() {
    var makeSelfResolutionError = function() {
      return new TypeError("circular promise resolution chain\u000a\u000a    See http://goo.gl/MqrFmX\u000a");
    };
    var reflectHandler = function() {
      return new Promise.PromiseInspection(this._target());
    };
    var apiRejection = function(msg) {
      return Promise.reject(new TypeError(msg));
    };
    function Proxyable() {}
    var UNDEFINED_BINDING = {};
    var util = $__require('41');
    var getDomain;
    if (util.isNode) {
      getDomain = function() {
        var ret = process.domain;
        if (ret === undefined)
          ret = null;
        return ret;
      };
    } else {
      getDomain = function() {
        return null;
      };
    }
    util.notEnumerableProp(Promise, "_getDomain", getDomain);
    var es5 = $__require('4b');
    var Async = $__require('43');
    var async = new Async();
    es5.defineProperty(Promise, "_async", {value: async});
    var errors = $__require('48');
    var TypeError = Promise.TypeError = errors.TypeError;
    Promise.RangeError = errors.RangeError;
    var CancellationError = Promise.CancellationError = errors.CancellationError;
    Promise.TimeoutError = errors.TimeoutError;
    Promise.OperationalError = errors.OperationalError;
    Promise.RejectionError = errors.OperationalError;
    Promise.AggregateError = errors.AggregateError;
    var INTERNAL = function() {};
    var APPLY = {};
    var NEXT_FILTER = {};
    var tryConvertToPromise = $__require('44')(Promise, INTERNAL);
    var PromiseArray = $__require('45')(Promise, INTERNAL, tryConvertToPromise, apiRejection, Proxyable);
    var Context = $__require('46')(Promise);
    var createContext = Context.create;
    var debug = $__require('47')(Promise, Context);
    var CapturedTrace = debug.CapturedTrace;
    var PassThroughHandlerContext = $__require('49')(Promise, tryConvertToPromise);
    var catchFilter = $__require('4a')(NEXT_FILTER);
    var nodebackForPromise = $__require('5d');
    var errorObj = util.errorObj;
    var tryCatch = util.tryCatch;
    function check(self, executor) {
      if (typeof executor !== "function") {
        throw new TypeError("expecting a function but got " + util.classString(executor));
      }
      if (self.constructor !== Promise) {
        throw new TypeError("the promise constructor cannot be invoked directly\u000a\u000a    See http://goo.gl/MqrFmX\u000a");
      }
    }
    function Promise(executor) {
      this._bitField = 0;
      this._fulfillmentHandler0 = undefined;
      this._rejectionHandler0 = undefined;
      this._promise0 = undefined;
      this._receiver0 = undefined;
      if (executor !== INTERNAL) {
        check(this, executor);
        this._resolveFromExecutor(executor);
      }
      this._promiseCreated();
      this._fireEvent("promiseCreated", this);
    }
    Promise.prototype.toString = function() {
      return "[object Promise]";
    };
    Promise.prototype.caught = Promise.prototype["catch"] = function(fn) {
      var len = arguments.length;
      if (len > 1) {
        var catchInstances = new Array(len - 1),
            j = 0,
            i;
        for (i = 0; i < len - 1; ++i) {
          var item = arguments[i];
          if (util.isObject(item)) {
            catchInstances[j++] = item;
          } else {
            return apiRejection("expecting an object but got " + util.classString(item));
          }
        }
        catchInstances.length = j;
        fn = arguments[i];
        return this.then(undefined, catchFilter(catchInstances, fn, this));
      }
      return this.then(undefined, fn);
    };
    Promise.prototype.reflect = function() {
      return this._then(reflectHandler, reflectHandler, undefined, this, undefined);
    };
    Promise.prototype.then = function(didFulfill, didReject) {
      if (debug.warnings() && arguments.length > 0 && typeof didFulfill !== "function" && typeof didReject !== "function") {
        var msg = ".then() only accepts functions but was passed: " + util.classString(didFulfill);
        if (arguments.length > 1) {
          msg += ", " + util.classString(didReject);
        }
        this._warn(msg);
      }
      return this._then(didFulfill, didReject, undefined, undefined, undefined);
    };
    Promise.prototype.done = function(didFulfill, didReject) {
      var promise = this._then(didFulfill, didReject, undefined, undefined, undefined);
      promise._setIsFinal();
    };
    Promise.prototype.spread = function(fn) {
      if (typeof fn !== "function") {
        return apiRejection("expecting a function but got " + util.classString(fn));
      }
      return this.all()._then(fn, undefined, undefined, APPLY, undefined);
    };
    Promise.prototype.toJSON = function() {
      var ret = {
        isFulfilled: false,
        isRejected: false,
        fulfillmentValue: undefined,
        rejectionReason: undefined
      };
      if (this.isFulfilled()) {
        ret.fulfillmentValue = this.value();
        ret.isFulfilled = true;
      } else if (this.isRejected()) {
        ret.rejectionReason = this.reason();
        ret.isRejected = true;
      }
      return ret;
    };
    Promise.prototype.all = function() {
      if (arguments.length > 0) {
        this._warn(".all() was passed arguments but it does not take any");
      }
      return new PromiseArray(this).promise();
    };
    Promise.prototype.error = function(fn) {
      return this.caught(util.originatesFromRejection, fn);
    };
    Promise.is = function(val) {
      return val instanceof Promise;
    };
    Promise.fromNode = Promise.fromCallback = function(fn) {
      var ret = new Promise(INTERNAL);
      ret._captureStackTrace();
      var multiArgs = arguments.length > 1 ? !!Object(arguments[1]).multiArgs : false;
      var result = tryCatch(fn)(nodebackForPromise(ret, multiArgs));
      if (result === errorObj) {
        ret._rejectCallback(result.e, true);
      }
      if (!ret._isFateSealed())
        ret._setAsyncGuaranteed();
      return ret;
    };
    Promise.all = function(promises) {
      return new PromiseArray(promises).promise();
    };
    Promise.cast = function(obj) {
      var ret = tryConvertToPromise(obj);
      if (!(ret instanceof Promise)) {
        ret = new Promise(INTERNAL);
        ret._captureStackTrace();
        ret._setFulfilled();
        ret._rejectionHandler0 = obj;
      }
      return ret;
    };
    Promise.resolve = Promise.fulfilled = Promise.cast;
    Promise.reject = Promise.rejected = function(reason) {
      var ret = new Promise(INTERNAL);
      ret._captureStackTrace();
      ret._rejectCallback(reason, true);
      return ret;
    };
    Promise.setScheduler = function(fn) {
      if (typeof fn !== "function") {
        throw new TypeError("expecting a function but got " + util.classString(fn));
      }
      var prev = async._schedule;
      async._schedule = fn;
      return prev;
    };
    Promise.prototype._then = function(didFulfill, didReject, _, receiver, internalData) {
      var haveInternalData = internalData !== undefined;
      var promise = haveInternalData ? internalData : new Promise(INTERNAL);
      var target = this._target();
      var bitField = target._bitField;
      if (!haveInternalData) {
        promise._propagateFrom(this, 3);
        promise._captureStackTrace();
        if (receiver === undefined && ((this._bitField & 2097152) !== 0)) {
          if (!((bitField & 50397184) === 0)) {
            receiver = this._boundValue();
          } else {
            receiver = target === this ? undefined : this._boundTo;
          }
        }
        this._fireEvent("promiseChained", this, promise);
      }
      var domain = getDomain();
      if (!((bitField & 50397184) === 0)) {
        var handler,
            value,
            settler = target._settlePromiseCtx;
        if (((bitField & 33554432) !== 0)) {
          value = target._rejectionHandler0;
          handler = didFulfill;
        } else if (((bitField & 16777216) !== 0)) {
          value = target._fulfillmentHandler0;
          handler = didReject;
          target._unsetRejectionIsUnhandled();
        } else {
          settler = target._settlePromiseLateCancellationObserver;
          value = new CancellationError("late cancellation observer");
          target._attachExtraTrace(value);
          handler = didReject;
        }
        async.invoke(settler, target, {
          handler: domain === null ? handler : (typeof handler === "function" && domain.bind(handler)),
          promise: promise,
          receiver: receiver,
          value: value
        });
      } else {
        target._addCallbacks(didFulfill, didReject, promise, receiver, domain);
      }
      return promise;
    };
    Promise.prototype._length = function() {
      return this._bitField & 65535;
    };
    Promise.prototype._isFateSealed = function() {
      return (this._bitField & 117506048) !== 0;
    };
    Promise.prototype._isFollowing = function() {
      return (this._bitField & 67108864) === 67108864;
    };
    Promise.prototype._setLength = function(len) {
      this._bitField = (this._bitField & -65536) | (len & 65535);
    };
    Promise.prototype._setFulfilled = function() {
      this._bitField = this._bitField | 33554432;
      this._fireEvent("promiseFulfilled", this);
    };
    Promise.prototype._setRejected = function() {
      this._bitField = this._bitField | 16777216;
      this._fireEvent("promiseRejected", this);
    };
    Promise.prototype._setFollowing = function() {
      this._bitField = this._bitField | 67108864;
      this._fireEvent("promiseResolved", this);
    };
    Promise.prototype._setIsFinal = function() {
      this._bitField = this._bitField | 4194304;
    };
    Promise.prototype._isFinal = function() {
      return (this._bitField & 4194304) > 0;
    };
    Promise.prototype._unsetCancelled = function() {
      this._bitField = this._bitField & (~65536);
    };
    Promise.prototype._setCancelled = function() {
      this._bitField = this._bitField | 65536;
      this._fireEvent("promiseCancelled", this);
    };
    Promise.prototype._setAsyncGuaranteed = function() {
      this._bitField = this._bitField | 134217728;
    };
    Promise.prototype._receiverAt = function(index) {
      var ret = index === 0 ? this._receiver0 : this[index * 4 - 4 + 3];
      if (ret === UNDEFINED_BINDING) {
        return undefined;
      } else if (ret === undefined && this._isBound()) {
        return this._boundValue();
      }
      return ret;
    };
    Promise.prototype._promiseAt = function(index) {
      return this[index * 4 - 4 + 2];
    };
    Promise.prototype._fulfillmentHandlerAt = function(index) {
      return this[index * 4 - 4 + 0];
    };
    Promise.prototype._rejectionHandlerAt = function(index) {
      return this[index * 4 - 4 + 1];
    };
    Promise.prototype._boundValue = function() {};
    Promise.prototype._migrateCallback0 = function(follower) {
      var bitField = follower._bitField;
      var fulfill = follower._fulfillmentHandler0;
      var reject = follower._rejectionHandler0;
      var promise = follower._promise0;
      var receiver = follower._receiverAt(0);
      if (receiver === undefined)
        receiver = UNDEFINED_BINDING;
      this._addCallbacks(fulfill, reject, promise, receiver, null);
    };
    Promise.prototype._migrateCallbackAt = function(follower, index) {
      var fulfill = follower._fulfillmentHandlerAt(index);
      var reject = follower._rejectionHandlerAt(index);
      var promise = follower._promiseAt(index);
      var receiver = follower._receiverAt(index);
      if (receiver === undefined)
        receiver = UNDEFINED_BINDING;
      this._addCallbacks(fulfill, reject, promise, receiver, null);
    };
    Promise.prototype._addCallbacks = function(fulfill, reject, promise, receiver, domain) {
      var index = this._length();
      if (index >= 65535 - 4) {
        index = 0;
        this._setLength(0);
      }
      if (index === 0) {
        this._promise0 = promise;
        this._receiver0 = receiver;
        if (typeof fulfill === "function") {
          this._fulfillmentHandler0 = domain === null ? fulfill : domain.bind(fulfill);
        }
        if (typeof reject === "function") {
          this._rejectionHandler0 = domain === null ? reject : domain.bind(reject);
        }
      } else {
        var base = index * 4 - 4;
        this[base + 2] = promise;
        this[base + 3] = receiver;
        if (typeof fulfill === "function") {
          this[base + 0] = domain === null ? fulfill : domain.bind(fulfill);
        }
        if (typeof reject === "function") {
          this[base + 1] = domain === null ? reject : domain.bind(reject);
        }
      }
      this._setLength(index + 1);
      return index;
    };
    Promise.prototype._proxy = function(proxyable, arg) {
      this._addCallbacks(undefined, undefined, arg, proxyable, null);
    };
    Promise.prototype._resolveCallback = function(value, shouldBind) {
      if (((this._bitField & 117506048) !== 0))
        return;
      if (value === this)
        return this._rejectCallback(makeSelfResolutionError(), false);
      var maybePromise = tryConvertToPromise(value, this);
      if (!(maybePromise instanceof Promise))
        return this._fulfill(value);
      if (shouldBind)
        this._propagateFrom(maybePromise, 2);
      var promise = maybePromise._target();
      if (promise === this) {
        this._reject(makeSelfResolutionError());
        return;
      }
      var bitField = promise._bitField;
      if (((bitField & 50397184) === 0)) {
        var len = this._length();
        if (len > 0)
          promise._migrateCallback0(this);
        for (var i = 1; i < len; ++i) {
          promise._migrateCallbackAt(this, i);
        }
        this._setFollowing();
        this._setLength(0);
        this._setFollowee(promise);
      } else if (((bitField & 33554432) !== 0)) {
        this._fulfill(promise._value());
      } else if (((bitField & 16777216) !== 0)) {
        this._reject(promise._reason());
      } else {
        var reason = new CancellationError("late cancellation observer");
        promise._attachExtraTrace(reason);
        this._reject(reason);
      }
    };
    Promise.prototype._rejectCallback = function(reason, synchronous, ignoreNonErrorWarnings) {
      var trace = util.ensureErrorObject(reason);
      var hasStack = trace === reason;
      if (!hasStack && !ignoreNonErrorWarnings && debug.warnings()) {
        var message = "a promise was rejected with a non-error: " + util.classString(reason);
        this._warn(message, true);
      }
      this._attachExtraTrace(trace, synchronous ? hasStack : false);
      this._reject(reason);
    };
    Promise.prototype._resolveFromExecutor = function(executor) {
      var promise = this;
      this._captureStackTrace();
      this._pushContext();
      var synchronous = true;
      var r = this._execute(executor, function(value) {
        promise._resolveCallback(value);
      }, function(reason) {
        promise._rejectCallback(reason, synchronous);
      });
      synchronous = false;
      this._popContext();
      if (r !== undefined) {
        promise._rejectCallback(r, true);
      }
    };
    Promise.prototype._settlePromiseFromHandler = function(handler, receiver, value, promise) {
      var bitField = promise._bitField;
      if (((bitField & 65536) !== 0))
        return;
      promise._pushContext();
      var x;
      if (receiver === APPLY) {
        if (!value || typeof value.length !== "number") {
          x = errorObj;
          x.e = new TypeError("cannot .spread() a non-array: " + util.classString(value));
        } else {
          x = tryCatch(handler).apply(this._boundValue(), value);
        }
      } else {
        x = tryCatch(handler).call(receiver, value);
      }
      var promiseCreated = promise._popContext();
      bitField = promise._bitField;
      if (((bitField & 65536) !== 0))
        return;
      if (x === NEXT_FILTER) {
        promise._reject(value);
      } else if (x === errorObj) {
        promise._rejectCallback(x.e, false);
      } else {
        debug.checkForgottenReturns(x, promiseCreated, "", promise, this);
        promise._resolveCallback(x);
      }
    };
    Promise.prototype._target = function() {
      var ret = this;
      while (ret._isFollowing())
        ret = ret._followee();
      return ret;
    };
    Promise.prototype._followee = function() {
      return this._rejectionHandler0;
    };
    Promise.prototype._setFollowee = function(promise) {
      this._rejectionHandler0 = promise;
    };
    Promise.prototype._settlePromise = function(promise, handler, receiver, value) {
      var isPromise = promise instanceof Promise;
      var bitField = this._bitField;
      var asyncGuaranteed = ((bitField & 134217728) !== 0);
      if (((bitField & 65536) !== 0)) {
        if (isPromise)
          promise._invokeInternalOnCancel();
        if (receiver instanceof PassThroughHandlerContext && receiver.isFinallyHandler()) {
          receiver.cancelPromise = promise;
          if (tryCatch(handler).call(receiver, value) === errorObj) {
            promise._reject(errorObj.e);
          }
        } else if (handler === reflectHandler) {
          promise._fulfill(reflectHandler.call(receiver));
        } else if (receiver instanceof Proxyable) {
          receiver._promiseCancelled(promise);
        } else if (isPromise || promise instanceof PromiseArray) {
          promise._cancel();
        } else {
          receiver.cancel();
        }
      } else if (typeof handler === "function") {
        if (!isPromise) {
          handler.call(receiver, value, promise);
        } else {
          if (asyncGuaranteed)
            promise._setAsyncGuaranteed();
          this._settlePromiseFromHandler(handler, receiver, value, promise);
        }
      } else if (receiver instanceof Proxyable) {
        if (!receiver._isResolved()) {
          if (((bitField & 33554432) !== 0)) {
            receiver._promiseFulfilled(value, promise);
          } else {
            receiver._promiseRejected(value, promise);
          }
        }
      } else if (isPromise) {
        if (asyncGuaranteed)
          promise._setAsyncGuaranteed();
        if (((bitField & 33554432) !== 0)) {
          promise._fulfill(value);
        } else {
          promise._reject(value);
        }
      }
    };
    Promise.prototype._settlePromiseLateCancellationObserver = function(ctx) {
      var handler = ctx.handler;
      var promise = ctx.promise;
      var receiver = ctx.receiver;
      var value = ctx.value;
      if (typeof handler === "function") {
        if (!(promise instanceof Promise)) {
          handler.call(receiver, value, promise);
        } else {
          this._settlePromiseFromHandler(handler, receiver, value, promise);
        }
      } else if (promise instanceof Promise) {
        promise._reject(value);
      }
    };
    Promise.prototype._settlePromiseCtx = function(ctx) {
      this._settlePromise(ctx.promise, ctx.handler, ctx.receiver, ctx.value);
    };
    Promise.prototype._settlePromise0 = function(handler, value, bitField) {
      var promise = this._promise0;
      var receiver = this._receiverAt(0);
      this._promise0 = undefined;
      this._receiver0 = undefined;
      this._settlePromise(promise, handler, receiver, value);
    };
    Promise.prototype._clearCallbackDataAtIndex = function(index) {
      var base = index * 4 - 4;
      this[base + 2] = this[base + 3] = this[base + 0] = this[base + 1] = undefined;
    };
    Promise.prototype._fulfill = function(value) {
      var bitField = this._bitField;
      if (((bitField & 117506048) >>> 16))
        return;
      if (value === this) {
        var err = makeSelfResolutionError();
        this._attachExtraTrace(err);
        return this._reject(err);
      }
      this._setFulfilled();
      this._rejectionHandler0 = value;
      if ((bitField & 65535) > 0) {
        if (((bitField & 134217728) !== 0)) {
          this._settlePromises();
        } else {
          async.settlePromises(this);
        }
      }
    };
    Promise.prototype._reject = function(reason) {
      var bitField = this._bitField;
      if (((bitField & 117506048) >>> 16))
        return;
      this._setRejected();
      this._fulfillmentHandler0 = reason;
      if (this._isFinal()) {
        return async.fatalError(reason, util.isNode);
      }
      if ((bitField & 65535) > 0) {
        async.settlePromises(this);
      } else {
        this._ensurePossibleRejectionHandled();
      }
    };
    Promise.prototype._fulfillPromises = function(len, value) {
      for (var i = 1; i < len; i++) {
        var handler = this._fulfillmentHandlerAt(i);
        var promise = this._promiseAt(i);
        var receiver = this._receiverAt(i);
        this._clearCallbackDataAtIndex(i);
        this._settlePromise(promise, handler, receiver, value);
      }
    };
    Promise.prototype._rejectPromises = function(len, reason) {
      for (var i = 1; i < len; i++) {
        var handler = this._rejectionHandlerAt(i);
        var promise = this._promiseAt(i);
        var receiver = this._receiverAt(i);
        this._clearCallbackDataAtIndex(i);
        this._settlePromise(promise, handler, receiver, reason);
      }
    };
    Promise.prototype._settlePromises = function() {
      var bitField = this._bitField;
      var len = (bitField & 65535);
      if (len > 0) {
        if (((bitField & 16842752) !== 0)) {
          var reason = this._fulfillmentHandler0;
          this._settlePromise0(this._rejectionHandler0, reason, bitField);
          this._rejectPromises(len, reason);
        } else {
          var value = this._rejectionHandler0;
          this._settlePromise0(this._fulfillmentHandler0, value, bitField);
          this._fulfillPromises(len, value);
        }
        this._setLength(0);
      }
      this._clearCancellationData();
    };
    Promise.prototype._settledValue = function() {
      var bitField = this._bitField;
      if (((bitField & 33554432) !== 0)) {
        return this._rejectionHandler0;
      } else if (((bitField & 16777216) !== 0)) {
        return this._fulfillmentHandler0;
      }
    };
    function deferResolve(v) {
      this.promise._resolveCallback(v);
    }
    function deferReject(v) {
      this.promise._rejectCallback(v, false);
    }
    Promise.defer = Promise.pending = function() {
      debug.deprecated("Promise.defer", "new Promise");
      var promise = new Promise(INTERNAL);
      return {
        promise: promise,
        resolve: deferResolve,
        reject: deferReject
      };
    };
    util.notEnumerableProp(Promise, "_makeSelfResolutionError", makeSelfResolutionError);
    $__require('4c')(Promise, INTERNAL, tryConvertToPromise, apiRejection, debug);
    $__require('4d')(Promise, INTERNAL, tryConvertToPromise, debug);
    $__require('4e')(Promise, PromiseArray, apiRejection, debug);
    $__require('4f')(Promise);
    $__require('50')(Promise);
    $__require('51')(Promise, PromiseArray, tryConvertToPromise, INTERNAL, debug);
    Promise.Promise = Promise;
    $__require('52')(Promise, PromiseArray, apiRejection, tryConvertToPromise, INTERNAL, debug);
    $__require('53')(Promise, apiRejection, tryConvertToPromise, createContext, INTERNAL, debug);
    $__require('54')(Promise, INTERNAL, debug);
    $__require('55')(Promise, apiRejection, INTERNAL, tryConvertToPromise, Proxyable, debug);
    $__require('56')(Promise);
    $__require('57')(Promise);
    $__require('58')(Promise, PromiseArray, tryConvertToPromise, apiRejection);
    $__require('59')(Promise, INTERNAL, tryConvertToPromise, apiRejection);
    $__require('5a')(Promise, PromiseArray, apiRejection, tryConvertToPromise, INTERNAL, debug);
    $__require('5b')(Promise, PromiseArray, debug);
    $__require('5c')(Promise, PromiseArray, apiRejection);
    $__require('5e')(Promise, INTERNAL);
    $__require('5f')(Promise);
    $__require('60')(Promise, INTERNAL);
    $__require('61')(Promise, INTERNAL);
    util.toFastProperties(Promise);
    util.toFastProperties(Promise.prototype);
    function fillTypes(value) {
      var p = new Promise(INTERNAL);
      p._fulfillmentHandler0 = value;
      p._rejectionHandler0 = value;
      p._promise0 = value;
      p._receiver0 = value;
    }
    fillTypes({a: 1});
    fillTypes({b: 2});
    fillTypes({c: 3});
    fillTypes(1);
    fillTypes(function() {});
    fillTypes(undefined);
    fillTypes(false);
    fillTypes(new Promise(INTERNAL));
    debug.setBounds(Async.firstLineError, util.lastLineError);
    return Promise;
  };
  return module.exports;
});

$__System.registerDynamic("20", ["62"], true, function($__require, exports, module) {
  "use strict";
  ;
  var define,
      global = this,
      GLOBAL = this;
  var old;
  if (typeof Promise !== "undefined")
    old = Promise;
  function noConflict() {
    try {
      if (Promise === bluebird)
        Promise = old;
    } catch (e) {}
    return bluebird;
  }
  var bluebird = $__require('62')();
  bluebird.noConflict = noConflict;
  module.exports = bluebird;
  return module.exports;
});

$__System.registerDynamic("1a", ["20"], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  var P,
      coroutine,
      defer,
      seqr,
      bind,
      slice$ = [].slice;
  coroutine = (P = $__require('20')).coroutine;
  defer = function() {
    var accept,
        reject,
        promise;
    accept = void 8;
    reject = void 8;
    promise = new P(function(a, r) {
      accept = a;
      return reject = r;
    });
    return {
      resolve: accept,
      reject: reject,
      promise: promise
    };
  };
  seqr = function(stepr) {
    return function() {
      var args,
          res$,
          i$,
          to$,
          thunks,
          thunk,
          finalizer,
          ch,
          fch,
          ref$,
          task;
      res$ = [];
      for (i$ = 0, to$ = arguments.length; i$ < to$; ++i$) {
        res$.push(arguments[i$]);
      }
      args = res$;
      thunks = {};
      thunk = function(name) {
        var ref$;
        return (ref$ = thunks[name]) != null ? ref$ : thunks[name] = defer();
      };
      finalizer = defer();
      ch = {
        get: function(name) {
          return thunk(name).promise;
        },
        'let': function(name, value) {
          return thunk(name).resolve(value);
        }
      };
      fch = (ref$ = clone$(ch), ref$['finally'] = function() {
        var args,
            res$,
            i$,
            to$,
            ref$;
        res$ = [];
        for (i$ = 0, to$ = arguments.length; i$ < to$; ++i$) {
          res$.push(arguments[i$]);
        }
        args = res$;
        return (ref$ = finalizer.promise)['finally'].apply(ref$, args);
      }, ref$);
      task = coroutine(stepr).apply(null, [fch].concat(slice$.call(args)));
      task['finally'](function() {
        var name,
            ref$,
            thunk,
            results$ = [];
        finalizer.resolve();
        for (name in ref$ = thunks) {
          thunk = ref$[name];
          if (thunk.promise.isPending()) {
            results$.push(thunk.reject("No value for '" + name + "'"));
          }
        }
        return results$;
      });
      return import$(task, ch);
    };
  };
  seqr.seqr = seqr;
  seqr.bind = bind = function(g) {
    return seqr(function*(ch) {
      var args,
          res$,
          i$,
          to$;
      res$ = [];
      for (i$ = 1, to$ = arguments.length; i$ < to$; ++i$) {
        res$.push(arguments[i$]);
      }
      args = res$;
      return (yield* g.apply(ch, args));
    });
  };
  module.exports = seqr;
  function clone$(it) {
    function fun() {}
    fun.prototype = it;
    return new fun;
  }
  function import$(obj, src) {
    var own = {}.hasOwnProperty;
    for (var key in src)
      if (own.call(src, key))
        obj[key] = src[key];
    return obj;
  }
  return module.exports;
});

$__System.registerDynamic("1", ["19", "1f", "3f", "1a"], true, function($__require, exports, module) {
  ;
  var define,
      global = this,
      GLOBAL = this;
  var $,
      deparam,
      experiments,
      seqr;
  $ = $__require('19');
  deparam = $__require('1f');
  experiments = $__require('3f');
  seqr = $__require('1a');
  $(seqr.bind(function*() {
    var opts,
        experimentName,
        ref$,
        experiment;
    opts = deparam(window.location.search.substring(1));
    experimentName = (ref$ = opts.experiment) != null ? ref$ : 'defaultExperiment';
    experiment = experiments[experimentName];
    (yield experiment());
  }));
  return module.exports;
});

})
(function(factory) {
  if (typeof define == 'function' && define.amd)
    define([], factory);
  else if (typeof module == 'object' && module.exports && typeof require == 'function')
    module.exports = factory();
  else
    factory();
});
back to top